diff --git a/docker-compose.yml b/docker-compose.yml
index df5e13d54..c6e0bd47c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -122,29 +122,29 @@ services:
image: pigx-codegen
container_name: pigx-codegen
- pigx-mp-manager:
+ pigx-mp-platform:
build:
context: ./
- dockerfile: ./pigx-visual/pigx-mp-manager/Dockerfile
+ dockerfile: ./pigx-visual/pigx-mp-platform/Dockerfile
restart: always
- image: pigx-mp-manager
- container_name: pigx-mp-manager
+ image: pigx-mp-platform
+ container_name: pigx-mp-platform
- pigx-pay:
+ pigx-pay-platform:
build:
context: ./
- dockerfile: ./pigx-visual/pigx-pay/Dockerfile
+ dockerfile: ./pigx-visual/pigx-pay-platform/Dockerfile
restart: always
- image: pigx-pay
- container_name: pigx-pay
+ image: pigx-pay-platform
+ container_name: pigx-pay-platform
- pigx-activiti:
+ pigx-oa-platform:
build:
context: ./
- dockerfile: ./pigx-visual/pigx-activiti/Dockerfile
+ dockerfile: ./pigx-visual/pigx-oa-platform/Dockerfile
restart: always
- image: pigx-activiti
- container_name: pigx-activiti
+ image: pigx-oa-platform
+ container_name: pigx-oa-platform
pigx-tx-manager:
build:
diff --git a/pigx-visual/pigx-mp-manager/.rebel.xml.bak b/pigx-visual/pigx-mp-platform/.rebel.xml.bak
similarity index 100%
rename from pigx-visual/pigx-mp-manager/.rebel.xml.bak
rename to pigx-visual/pigx-mp-platform/.rebel.xml.bak
diff --git a/pigx-visual/pigx-mp-manager/Dockerfile b/pigx-visual/pigx-mp-platform/Dockerfile
similarity index 57%
rename from pigx-visual/pigx-mp-manager/Dockerfile
rename to pigx-visual/pigx-mp-platform/Dockerfile
index 7a6e5b1de..213f87580 100644
--- a/pigx-visual/pigx-mp-manager/Dockerfile
+++ b/pigx-visual/pigx-mp-platform/Dockerfile
@@ -4,12 +4,12 @@ MAINTAINER wangiegie@gmail.com
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
-RUN mkdir -p /pigx-mp-manager
+RUN mkdir -p /pigx-pay-platform
-WORKDIR /pigx-mp-manager
+WORKDIR /pigx-pay-platform
EXPOSE 6000
-ADD ./pigx-visual/pigx-mp-manager/target/pigx-mp-manager.jar ./
+ADD ./pigx-visual/pigx-pay-platform/target/pigx-pay-platform.jar ./
-CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-mp-manager.jar
+CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-pay-platform.jar
diff --git a/pigx-visual/pigx-mp-manager/pom.xml b/pigx-visual/pigx-mp-platform/pom.xml
similarity index 98%
rename from pigx-visual/pigx-mp-manager/pom.xml
rename to pigx-visual/pigx-mp-platform/pom.xml
index aba302d6f..cc731a025 100755
--- a/pigx-visual/pigx-mp-manager/pom.xml
+++ b/pigx-visual/pigx-mp-platform/pom.xml
@@ -9,7 +9,7 @@
3.4.0
- pigx-mp-manager
+ pigx-mp-platform
jar
微信公众号管理模块
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpContextHolder.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpContextHolder.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpContextHolder.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpContextHolder.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgResController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgResController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgResController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxFansMsgResController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxMenuController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMenuController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxMenuController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxMenuController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsg.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsg.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsg.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsg.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsgRes.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsgRes.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsgRes.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxFansMsgRes.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxMpMenu.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxMpMenu.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxMpMenu.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/entity/WxMpMenu.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgMapper.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgMapper.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgMapper.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgMapper.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgResMapper.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgResMapper.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgResMapper.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxFansMsgResMapper.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxMenuMapper.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxMenuMapper.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxMenuMapper.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/mapper/WxMenuMapper.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgResService.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgResService.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgResService.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgResService.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgService.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgService.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgService.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxFansMsgService.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxMenuService.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxMenuService.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxMenuService.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/WxMenuService.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgResServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgResServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgResServiceImpl.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgResServiceImpl.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgServiceImpl.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxFansMsgServiceImpl.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxMenuServiceImpl.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxMenuServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxMenuServiceImpl.java
rename to pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxMenuServiceImpl.java
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/bootstrap.yml b/pigx-visual/pigx-mp-platform/src/main/resources/bootstrap.yml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/bootstrap.yml
rename to pigx-visual/pigx-mp-platform/src/main/resources/bootstrap.yml
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountFansMapper.xml b/pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxAccountFansMapper.xml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountFansMapper.xml
rename to pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxAccountFansMapper.xml
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountMapper.xml b/pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxAccountMapper.xml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountMapper.xml
rename to pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxAccountMapper.xml
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxFansMsgMapper.xml b/pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxFansMsgMapper.xml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxFansMsgMapper.xml
rename to pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxFansMsgMapper.xml
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxFansMsgResMapper.xml b/pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxFansMsgResMapper.xml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxFansMsgResMapper.xml
rename to pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxFansMsgResMapper.xml
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxMenuMapper.xml b/pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxMenuMapper.xml
similarity index 100%
rename from pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxMenuMapper.xml
rename to pigx-visual/pigx-mp-platform/src/main/resources/mapper/WxMenuMapper.xml
diff --git a/pigx-visual/pigx-activiti/Dockerfile b/pigx-visual/pigx-oa-platform/Dockerfile
similarity index 57%
rename from pigx-visual/pigx-activiti/Dockerfile
rename to pigx-visual/pigx-oa-platform/Dockerfile
index eb6a266d7..b7c69878d 100644
--- a/pigx-visual/pigx-activiti/Dockerfile
+++ b/pigx-visual/pigx-oa-platform/Dockerfile
@@ -4,12 +4,12 @@ MAINTAINER wangiegie@gmail.com
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
-RUN mkdir -p /pigx-activiti
+RUN mkdir -p /pigx-oa-platform
-WORKDIR /pigx-activiti
+WORKDIR /pigx-oa-platform
EXPOSE 5005
-ADD ./pigx-visual/pigx-activiti/target/pigx-activiti.jar ./
+ADD ./pigx-visual/pigx-oa-platform/target/pigx-oa-platform.jar ./
-CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-activiti.jar
+CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-oa-platform.jar
diff --git a/pigx-visual/pigx-activiti/pom.xml b/pigx-visual/pigx-oa-platform/pom.xml
similarity index 99%
rename from pigx-visual/pigx-activiti/pom.xml
rename to pigx-visual/pigx-oa-platform/pom.xml
index 61f3fd408..892d4470c 100644
--- a/pigx-visual/pigx-activiti/pom.xml
+++ b/pigx-visual/pigx-oa-platform/pom.xml
@@ -26,7 +26,7 @@
3.4.0
- pigx-activiti
+ pigx-oa-platform
jar
工作流管理模块
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/PigxActivitiApplication.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/PigxActivitiApplication.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/PigxActivitiApplication.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/PigxActivitiApplication.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/EditorController.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/EditorController.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/EditorController.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/EditorController.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/LeaveBillController.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/LeaveBillController.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/LeaveBillController.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/LeaveBillController.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/ModelController.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/ModelController.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/ModelController.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/ModelController.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/ProcessController.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/ProcessController.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/ProcessController.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/ProcessController.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/TaskController.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/TaskController.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/controller/TaskController.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/controller/TaskController.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/CommentDto.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/CommentDto.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/CommentDto.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/CommentDto.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/LeaveBillDto.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/LeaveBillDto.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/LeaveBillDto.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/LeaveBillDto.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/ModelForm.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/ModelForm.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/ModelForm.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/ModelForm.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/ProcessDefDTO.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/ProcessDefDTO.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/ProcessDefDTO.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/ProcessDefDTO.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/StartTaskForm.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/StartTaskForm.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/StartTaskForm.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/StartTaskForm.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/TaskDTO.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/TaskDTO.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/dto/TaskDTO.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/dto/TaskDTO.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/entity/LeaveBill.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/entity/LeaveBill.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/entity/LeaveBill.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/entity/LeaveBill.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/mapper/LeaveBillMapper.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/mapper/LeaveBillMapper.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/mapper/LeaveBillMapper.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/mapper/LeaveBillMapper.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ActTaskService.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ActTaskService.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ActTaskService.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ActTaskService.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/EditorService.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/EditorService.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/EditorService.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/EditorService.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/LeaveBillService.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/LeaveBillService.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/LeaveBillService.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/LeaveBillService.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ModelService.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ModelService.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ModelService.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ModelService.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ProcessService.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ProcessService.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/ProcessService.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/ProcessService.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ActTaskServiceImpl.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ActTaskServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ActTaskServiceImpl.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ActTaskServiceImpl.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/EditorServiceImpl.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/EditorServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/EditorServiceImpl.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/EditorServiceImpl.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/LeaveBillServiceImpl.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/LeaveBillServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/LeaveBillServiceImpl.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/LeaveBillServiceImpl.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ModelServiceImpl.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ModelServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ModelServiceImpl.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ModelServiceImpl.java
diff --git a/pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ProcessServiceImpl.java b/pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ProcessServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/service/impl/ProcessServiceImpl.java
rename to pigx-visual/pigx-oa-platform/src/main/java/com/pig4cloud/pigx/act/service/impl/ProcessServiceImpl.java
diff --git a/pigx-visual/pigx-activiti/src/main/resources/bootstrap.yml b/pigx-visual/pigx-oa-platform/src/main/resources/bootstrap.yml
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/bootstrap.yml
rename to pigx-visual/pigx-oa-platform/src/main/resources/bootstrap.yml
diff --git a/pigx-visual/pigx-activiti/src/main/resources/mapper/LeaveBillMapper.xml b/pigx-visual/pigx-oa-platform/src/main/resources/mapper/LeaveBillMapper.xml
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/mapper/LeaveBillMapper.xml
rename to pigx-visual/pigx-oa-platform/src/main/resources/mapper/LeaveBillMapper.xml
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/bg.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/bg.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/bg.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/bg.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/breadcrumbs.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/breadcrumbs.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/breadcrumbs.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/breadcrumbs.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/checker-bg.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/checker-bg.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/checker-bg.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/checker-bg.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/blue/message_catch.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/blue/message_catch.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/blue/message_catch.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/blue/message_catch.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/business_rule.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/business_rule.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/business_rule.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/business_rule.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/error_catch.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/error_catch.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/error_catch.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/error_catch.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/error_throw.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/error_throw.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/error_throw.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/error_throw.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/manual.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/manual.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/manual.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/manual.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/message_catch.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/message_catch.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/message_catch.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/message_catch.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/message_throw.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/message_throw.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/message_throw.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/message_throw.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/receive.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/receive.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/receive.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/receive.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/script.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/script.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/script.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/script.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/send.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/send.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/send.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/send.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/service.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/service.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/service.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/service.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/signal_catch.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/signal_catch.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/signal_catch.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/signal_catch.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/signal_throw.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/signal_throw.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/signal_throw.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/signal_throw.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/timer.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/timer.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/timer.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/timer.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/user.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/user.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/images/deployer/user.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/images/deployer/user.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/index.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/index.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/index.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/index.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ActivitiRest.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ActivitiRest.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ActivitiRest.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ActivitiRest.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ActivityImpl.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ActivityImpl.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ActivityImpl.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ActivityImpl.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/Color.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/Color.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/Color.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/Color.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/LineBreakMeasurer.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/LineBreakMeasurer.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/LineBreakMeasurer.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/LineBreakMeasurer.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/Polyline.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/Polyline.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/Polyline.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/Polyline.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ProcessDiagramCanvas.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ProcessDiagramCanvas.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ProcessDiagramCanvas.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ProcessDiagramCanvas.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ProcessDiagramGenerator.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ProcessDiagramGenerator.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/ProcessDiagramGenerator.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/ProcessDiagramGenerator.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.asyncqueue.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.asyncqueue.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.asyncqueue.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.asyncqueue.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.progressbar.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.progressbar.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jquery/jquery.progressbar.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jquery/jquery.progressbar.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jstools.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jstools.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/jstools.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/jstools.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael.2.1.1.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael.2.1.1.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael.2.1.1.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael.2.1.1.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael_uncompressed.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael_uncompressed.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/raphael_uncompressed.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/raphael_uncompressed.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/textlayout.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/textlayout.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/js/textlayout.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/js/textlayout.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/style.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/style.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/diagram-viewer/style.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/diagram-viewer/style.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/app-cfg.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/app-cfg.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/app-cfg.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/app-cfg.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/app.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/app.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/app.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/app.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-assignment-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-assignment-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-assignment-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-assignment-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-condition-expression-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-condition-expression-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-condition-expression-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-condition-expression-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-custom-controllers.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-custom-controllers.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-custom-controllers.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-custom-controllers.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-default-controllers.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-default-controllers.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-default-controllers.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-default-controllers.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-event-listeners-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-event-listeners-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-event-listeners-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-event-listeners-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-execution-listeners-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-execution-listeners-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-execution-listeners-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-execution-listeners-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-fields-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-fields-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-fields-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-fields-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-form-properties-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-form-properties-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-form-properties-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-form-properties-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-in-parameters-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-in-parameters-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-in-parameters-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-in-parameters-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-message-definitions-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-message-definitions-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-message-definitions-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-message-definitions-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-message-scope-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-message-scope-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-message-scope-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-message-scope-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-multiinstance-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-multiinstance-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-multiinstance-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-multiinstance-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-out-parameters-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-out-parameters-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-out-parameters-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-out-parameters-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-sequenceflow-order-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-sequenceflow-order-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-sequenceflow-order-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-sequenceflow-order-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-signal-definitions-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-signal-definitions-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-signal-definitions-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-signal-definitions-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-signal-scope-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-signal-scope-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-signal-scope-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-signal-scope-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/assignment-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/assignment-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/boolean-property-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/boolean-property-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/boolean-property-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/boolean-property-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/condition-expression-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/condition-expression-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/default-value-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/default-value-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/default-value-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/default-value-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/event-listeners-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/event-listeners-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/execution-listeners-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/execution-listeners-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/feedback-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/feedback-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/feedback-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/feedback-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/fields-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/fields-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/form-properties-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/form-properties-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/in-parameters-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/in-parameters-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-definitions-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-definitions-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-property-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-property-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/message-property-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/message-property-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/multiinstance-property-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/multiinstance-property-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/multiinstance-property-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/multiinstance-property-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/out-parameters-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/out-parameters-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/sequenceflow-order-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-definitions-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-definitions-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-property-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-property-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/signal-property-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/signal-property-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/string-property-write-mode-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/string-property-write-mode-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/string-property-write-mode-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/string-property-write-mode-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/subprocess-reference-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-display-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-display-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-display-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-display-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/task-listeners-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/text-popup.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/text-popup.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/text-popup.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/text-popup.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/text-property-write-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/text-property-write-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/properties/text-property-write-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/properties/text-property-write-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar-custom-actions.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar-custom-actions.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar-custom-actions.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar-custom-actions.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar-default-actions.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar-default-actions.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar-default-actions.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar-default-actions.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/toolbar.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/toolbar.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/url-config.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/url-config.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/configuration/url-config.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/configuration/url-config.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style-common.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style-common.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style-common.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style-common.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style-editor.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style-editor.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style-editor.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style-editor.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/css/style.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/css/style.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-config.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-config.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-config.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-config.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-utils.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-utils.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor-utils.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor-utils.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/css/editor.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/css/editor.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/css/editor.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/css/editor.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_de.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_de.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_de.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_de.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/oryx.debug.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/oryx.debug.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/oryx.debug.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/oryx.debug.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/oryx.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/oryx.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/editor/oryx.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/editor/oryx.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/eventbus.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/eventbus.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/eventbus.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/eventbus.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.eot b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.eot
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.eot
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.eot
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.svg b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.svg
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.svg
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.svg
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.ttf b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.ttf
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.ttf
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.ttf
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.woff b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.woff
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.woff
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/activiti-admin-webfont.woff
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.eot b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.eot
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.eot
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.eot
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.ttf b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.ttf
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.ttf
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.ttf
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.woff b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.woff
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.woff
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/header-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/header-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/header-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/header-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/i18n/en.json b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/i18n/en.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/i18n/en.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/i18n/en.json
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/i18n/en.json_bak b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/i18n/en.json_bak
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/i18n/en.json_bak
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/i18n/en.json_bak
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/bpmn-error.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/bpmn-error.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/bpmn-error.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/bpmn-error.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/bpmn-warning.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/bpmn-warning.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/bpmn-warning.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/bpmn-warning.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/datadefinition.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/datadefinition.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/datadefinition.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/datadefinition.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/delete.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/delete.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/delete.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/delete.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/loading.gif b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/loading.gif
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/loading.gif
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/loading.gif
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/logo-2x.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/logo-2x.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/logo-2x.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/logo-2x.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/logo.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/logo.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/logo.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/logo.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/nw-handle-dark.gif b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/nw-handle-dark.gif
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/nw-handle-dark.gif
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/nw-handle-dark.gif
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/se-handle-dark.gif b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/se-handle-dark.gif
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/se-handle-dark.gif
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/se-handle-dark.gif
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/shapemenu_highlight.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/shapemenu_highlight.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/shapemenu_highlight.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/shapemenu_highlight.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/wrench.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/wrench.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/images/wrench.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/images/wrench.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-dragdrop.min-1.0.3.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-dragdrop.min-1.0.3.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-dragdrop.min-1.0.3.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-dragdrop.min-1.0.3.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-dragdrop_1.0.7/angular-dragdrop.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-dragdrop_1.0.7/angular-dragdrop.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-dragdrop_1.0.7/angular-dragdrop.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-dragdrop_1.0.7/angular-dragdrop.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-scroll_0.5.7/angular-scroll.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-scroll_0.5.7/angular-scroll.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-scroll_0.5.7/angular-scroll.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-scroll_0.5.7/angular-scroll.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.tpl.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.tpl.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.tpl.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-strap_2.0.5/angular-strap.tpl.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/.bower.json b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/.bower.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/.bower.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/.bower.json
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/.bower.json b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/.bower.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/.bower.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/.bower.json
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular_1.2.13/angular-animate.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular_1.2.13/angular-animate.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular_1.2.13/angular-animate.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular_1.2.13/angular-animate.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular_1.2.13/angular.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular_1.2.13/angular.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/angular_1.2.13/angular.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/angular_1.2.13/angular.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.min.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.min.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.min.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.min.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.eot b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.eot
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.eot
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.eot
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.ttf b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.ttf
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.ttf
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.ttf
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.woff b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.woff
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.woff
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.bower.json b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.bower.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.bower.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.bower.json
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.gitignore b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.gitignore
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.gitignore
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/.gitignore
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CHANGES b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CHANGES
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CHANGES
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CHANGES
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CONTRIBUTORS.md b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CONTRIBUTORS.md
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CONTRIBUTORS.md
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/CONTRIBUTORS.md
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/LICENSE b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/LICENSE
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/LICENSE
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/LICENSE
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/README.md b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/README.md
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/README.md
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/README.md
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-sham.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/es5-shim.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/package.json b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/package.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/package.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/package.json
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-kill.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-kill.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-kill.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-kill.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-matchers.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-matchers.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-matchers.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h-matchers.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/helpers/h.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.min.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.min.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.min.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/index.min.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine-html.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine-html.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine-html.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine-html.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine_favicon.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine_favicon.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine_favicon.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/jasmine_favicon.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/json2.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/json2.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/json2.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/lib/json2.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-array.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-array.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-array.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-array.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-date.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-date.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-date.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-date.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-function.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-function.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-function.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-function.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-number.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-number.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-number.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-number.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-object.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-object.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-object.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-object.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-string.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-string.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-string.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/es5-shim-15.3.4.5/tests/spec/s-string.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery-ui-1.10.3.custom.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery-ui-1.10.3.custom.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery-ui-1.10.3.custom.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery-ui-1.10.3.custom.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery.autogrow-textarea.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery.autogrow-textarea.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery.autogrow-textarea.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery.autogrow-textarea.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.map b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.map
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.map
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/jquery_1.11.0/jquery.min.map
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/LICENSE b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/LICENSE
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/LICENSE
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/LICENSE
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/json3_3.2.6/lib/json3.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/momentjs_2.5.1/momentjs.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/momentjs_2.5.1/momentjs.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/momentjs_2.5.1/momentjs.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/momentjs_2.5.1/momentjs.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/mousetrap-1.4.5.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/mousetrap-1.4.5.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/mousetrap-1.4.5.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/mousetrap-1.4.5.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ng-grid-2.0.7-min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ng-grid-2.0.7-min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ng-grid-2.0.7-min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ng-grid-2.0.7-min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ng-grid-2.0.7.min.css b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ng-grid-2.0.7.min.css
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ng-grid-2.0.7.min.css
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ng-grid-2.0.7.min.css
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/path_parser.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/path_parser.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/path_parser.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/path_parser.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/prototype-1.5.1.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/prototype-1.5.1.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/prototype-1.5.1.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/prototype-1.5.1.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ui-utils.min-0.0.4.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ui-utils.min-0.0.4.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/libs/ui-utils.min-0.0.4.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/libs/ui-utils.min-0.0.4.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/partials/root-stencil-item-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/partials/root-stencil-item-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/partials/root-stencil-item-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/partials/root-stencil-item-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/partials/stencil-item-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/partials/stencil-item-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/partials/stencil-item-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/partials/stencil-item-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/plugins.xml b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/plugins.xml
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/plugins.xml
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/plugins.xml
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/icon-template.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/icon-template.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/icon-template.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/icon-template.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/save-model.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/save-model.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/save-model.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/save-model.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/select-shape.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/select-shape.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/select-shape.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/select-shape.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/unsaved-changes.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/unsaved-changes.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/popups/unsaved-changes.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/popups/unsaved-changes.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/select-shape-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/select-shape-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/select-shape-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/select-shape-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencil-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencil-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencil-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencil-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.collapsed.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.collapsed.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.collapsed.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.collapsed.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/event.subprocess.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/expanded.subprocess.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/expanded.subprocess.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/expanded.subprocess.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/expanded.subprocess.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.business.rule.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.business.rule.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.business.rule.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.business.rule.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.camel.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.camel.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.camel.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.camel.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.manual.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.manual.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.manual.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.manual.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.mule.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.mule.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.mule.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.mule.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.receive.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.receive.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.receive.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.receive.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.script.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.script.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.script.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.script.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.send.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.send.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.send.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.send.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.service.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.service.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.service.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.service.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.shell.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.shell.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.shell.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.shell.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.user.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.user.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.user.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/list/type.user.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/subprocess.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/subprocess.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/subprocess.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/subprocess.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/task.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/task.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/task.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/activity/task.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/artifact/text.annotation.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/artifact/text.annotation.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/artifact/text.annotation.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/artifact/text.annotation.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/cancel.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/cancel.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/cancel.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/cancel.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/compensation.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/compensation.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/compensation.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/compensation.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/error.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/error.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/error.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/error.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/message.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/message.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/message.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/message.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/signal.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/signal.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/signal.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/signal.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/timer.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/timer.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/timer.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/catching/timer.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.undirected.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.undirected.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.undirected.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.undirected.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.unidirectional.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.unidirectional.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.unidirectional.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/association.unidirectional.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/messageflow.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/messageflow.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/messageflow.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/messageflow.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/sequenceflow.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/sequenceflow.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/sequenceflow.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/connector/sequenceflow.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/dataobject/data.store.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/dataobject/data.store.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/dataobject/data.store.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/dataobject/data.store.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/diagram.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/diagram.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/diagram.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/diagram.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/cancel.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/cancel.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/cancel.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/cancel.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/error.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/error.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/error.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/error.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/none.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/none.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/none.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/none.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/terminate.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/terminate.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/terminate.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/endevent/terminate.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/eventbased.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/eventbased.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/eventbased.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/eventbased.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/exclusive.databased.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/exclusive.databased.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/exclusive.databased.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/exclusive.databased.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/inclusive.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/inclusive.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/inclusive.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/inclusive.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/parallel.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/parallel.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/parallel.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/gateway/parallel.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/error.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/error.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/error.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/error.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/message.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/message.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/message.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/message.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/none.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/none.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/none.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/none.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/signal.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/signal.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/signal.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/signal.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/timer.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/timer.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/timer.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/startevent/timer.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/lane.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/lane.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/lane.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/lane.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/pool.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/pool.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/pool.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/swimlane/pool.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/none.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/none.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/none.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/none.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/signal.png b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/signal.png
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/signal.png
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/stencilsets/bpmn2.0/icons/throwing/signal.png
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/editor-app/toolbar-controller.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/toolbar-controller.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/editor-app/toolbar-controller.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/editor-app/toolbar-controller.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/favicon.ico b/pigx-visual/pigx-oa-platform/src/main/resources/static/favicon.ico
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/favicon.ico
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/favicon.ico
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/js/ajax-util.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/js/ajax-util.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/js/ajax-util.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/js/ajax-util.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/lib/js/jquery-1.10.2.min.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/jquery-1.10.2.min.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/lib/js/jquery-1.10.2.min.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/jquery-1.10.2.min.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/lib/js/jquery.cookie.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/jquery.cookie.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/lib/js/jquery.cookie.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/jquery.cookie.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/lib/js/template.js b/pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/template.js
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/lib/js/template.js
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/lib/js/template.js
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/model-list.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/model-list.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/model-list.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/model-list.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/static/modeler.html b/pigx-visual/pigx-oa-platform/src/main/resources/static/modeler.html
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/static/modeler.html
rename to pigx-visual/pigx-oa-platform/src/main/resources/static/modeler.html
diff --git a/pigx-visual/pigx-activiti/src/main/resources/stencilset.json b/pigx-visual/pigx-oa-platform/src/main/resources/stencilset.json
similarity index 100%
rename from pigx-visual/pigx-activiti/src/main/resources/stencilset.json
rename to pigx-visual/pigx-oa-platform/src/main/resources/stencilset.json
diff --git a/pigx-visual/pigx-pay/Dockerfile b/pigx-visual/pigx-pay-platform/Dockerfile
similarity index 57%
rename from pigx-visual/pigx-pay/Dockerfile
rename to pigx-visual/pigx-pay-platform/Dockerfile
index a374e99aa..aa2dd0e88 100644
--- a/pigx-visual/pigx-pay/Dockerfile
+++ b/pigx-visual/pigx-pay-platform/Dockerfile
@@ -4,12 +4,12 @@ MAINTAINER wangiegie@gmail.com
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
-RUN mkdir -p /pigx-pay
+RUN mkdir -p /pigx-pay-platform
-WORKDIR /pigx-pay
+WORKDIR /pigx-pay-platform
EXPOSE 5010
-ADD ./pigx-visual/pigx-pay/target/pigx-pay.jar ./
+ADD ./pigx-visual/pigx-pay-platform/target/pigx-pay-platform.jar ./
-CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-pay.jar
+CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-pay-platform.jar
diff --git a/pigx-visual/pigx-pay/pom.xml b/pigx-visual/pigx-pay-platform/pom.xml
similarity index 98%
rename from pigx-visual/pigx-pay/pom.xml
rename to pigx-visual/pigx-pay-platform/pom.xml
index 7a2d38731..8699b8e89 100755
--- a/pigx-visual/pigx-pay/pom.xml
+++ b/pigx-visual/pigx-pay-platform/pom.xml
@@ -9,7 +9,7 @@
3.4.0
- pigx-pay
+ pigx-pay-platform
jar
支付系统
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/PigxPayApplication.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/AliPayConfig.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/AliPayConfig.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/AliPayConfig.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/AliPayConfig.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayConfigParmaInitRunner.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/SequenceConfig.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/WxPayConfig.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/WxPayConfig.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/config/WxPayConfig.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/WxPayConfig.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayChannelController.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayRefundOrderController.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayTradeOrderController.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayChannel.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayGoodsOrder.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayNotifyRecord.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayRefundOrder.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/entity/PayTradeOrder.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/MessageDuplicateCheckerHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/MessageDuplicateCheckerHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/MessageDuplicateCheckerHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/MessageDuplicateCheckerHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayNotifyCallbakHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/PayNotifyCallbakHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayNotifyCallbakHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/PayNotifyCallbakHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/PayOrderHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayNotifyCallbakHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayNotifyCallbakHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayNotifyCallbakHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayNotifyCallbakHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayOrderHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayOrderHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayOrderHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AbstractPayOrderHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayPayNotifyCallbackHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayPayNotifyCallbackHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayPayNotifyCallbackHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayPayNotifyCallbackHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayWapPayOrderHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayWapPayOrderHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayWapPayOrderHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/AlipayWapPayOrderHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/MessageRedisDuplicateCheckerHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/MessageRedisDuplicateCheckerHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/MessageRedisDuplicateCheckerHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/MessageRedisDuplicateCheckerHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatMpPayOrderHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatMpPayOrderHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatMpPayOrderHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatMpPayOrderHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatPayNotifyCallbackHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatPayNotifyCallbackHandler.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatPayNotifyCallbackHandler.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/WeChatPayNotifyCallbackHandler.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayChannelMapper.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayGoodsOrderMapper.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayNotifyRecordMapper.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayRefundOrderMapper.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/mapper/PayTradeOrderMapper.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayChannelService.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayNotifyRecordService.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayRefundOrderService.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayTradeOrderService.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayChannelServiceImpl.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayNotifyRecordServiceImpl.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayRefundOrderServiceImpl.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayTradeOrderServiceImpl.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/OrderStatusEnum.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java
diff --git a/pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/TradeStatusEnum.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/TradeStatusEnum.java
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/java/com/pig4cloud/pigx/pay/utils/TradeStatusEnum.java
rename to pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/TradeStatusEnum.java
diff --git a/pigx-visual/pigx-pay/src/main/resources/bootstrap.yml b/pigx-visual/pigx-pay-platform/src/main/resources/bootstrap.yml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/bootstrap.yml
rename to pigx-visual/pigx-pay-platform/src/main/resources/bootstrap.yml
diff --git a/pigx-visual/pigx-pay/src/main/resources/logback-spring.xml b/pigx-visual/pigx-pay-platform/src/main/resources/logback-spring.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/logback-spring.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/logback-spring.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml b/pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayChannelMapper.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/mapper/PayChannelMapper.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayChannelMapper.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml b/pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayGoodsOrderMapper.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/mapper/PayGoodsOrderMapper.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayGoodsOrderMapper.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml b/pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayNotifyRecordMapper.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/mapper/PayNotifyRecordMapper.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayNotifyRecordMapper.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml b/pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayRefundOrderMapper.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/mapper/PayRefundOrderMapper.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayRefundOrderMapper.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml b/pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayTradeOrderMapper.xml
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/mapper/PayTradeOrderMapper.xml
rename to pigx-visual/pigx-pay-platform/src/main/resources/mapper/PayTradeOrderMapper.xml
diff --git a/pigx-visual/pigx-pay/src/main/resources/templates/pay.ftl b/pigx-visual/pigx-pay-platform/src/main/resources/templates/pay.ftl
similarity index 100%
rename from pigx-visual/pigx-pay/src/main/resources/templates/pay.ftl
rename to pigx-visual/pigx-pay-platform/src/main/resources/templates/pay.ftl
diff --git a/pigx-visual/pigx-sentinel-dashboard/Dockerfile b/pigx-visual/pigx-sentinel-dashboard/Dockerfile
new file mode 100644
index 000000000..7f4b414f2
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/Dockerfile
@@ -0,0 +1,15 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
+RUN mkdir -p /pigx-sentinel-dashboard
+
+WORKDIR /pigx-sentinel-dashboard
+
+EXPOSE 5010
+
+ADD ./pigx-visual/pigx-sentinel-dashboard/target/pigx-sentinel-dashboard.jar ./
+
+CMD sleep 120;java -Xms128m -Xmx256m -Djava.security.egd=file:/dev/./urandom -jar pigx-sentinel-dashboard.jar
diff --git a/pigx-visual/pigx-sentinel-dashboard/pom.xml b/pigx-visual/pigx-sentinel-dashboard/pom.xml
new file mode 100755
index 000000000..f0b7bbe58
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/pom.xml
@@ -0,0 +1,114 @@
+
+
+ 4.0.0
+
+
+ com.pig4cloud
+ pigx-visual
+ 3.4.0
+
+
+ pigx-sentinel-dashboard
+ jar
+
+
+
+ com.alibaba.csp
+ sentinel-core
+
+
+ com.alibaba.csp
+ sentinel-web-servlet
+ 1.6.3
+
+
+ com.alibaba.csp
+ sentinel-transport-simple-http
+
+
+ com.alibaba.csp
+ sentinel-parameter-flow-control
+ 1.6.3
+
+
+ com.alibaba.csp
+ sentinel-api-gateway-adapter-common
+ 1.6.3
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+ log4j
+ log4j
+ 1.2.14
+
+
+
+ commons-lang
+ commons-lang
+ 2.6
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.3
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4.5
+
+
+ org.apache.httpcomponents
+ httpasyncclient
+ 4.1.3
+
+
+ org.apache.httpcomponents
+ httpcore-nio
+ 4.4.6
+
+
+ com.alibaba
+ fastjson
+ 1.2.58
+
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+ test
+
+
+
+
+ pigx-sentinel-dashboard
+
+
+ src/main/resources
+
+
+
+ src/main/webapp/
+
+ resources/node_modules/**
+
+
+
+
+
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/PigxSentinelApplication.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/PigxSentinelApplication.java
new file mode 100755
index 000000000..9d87f81f0
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/PigxSentinelApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard;
+
+import com.alibaba.csp.sentinel.init.InitExecutor;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author nacos
+ *
+ * sentinel console 源码运行,方便开发
+ * 生产建议从官网下载最新版配置运行
+ */
+@SpringBootApplication
+public class PigxSentinelApplication {
+
+ public static void main(String[] args) {
+ triggerSentinelInit();
+ SpringApplication.run(PigxSentinelApplication.class, args);
+ }
+
+ private static void triggerSentinelInit() {
+ new Thread(InitExecutor::doInit).start();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/AuthService.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/AuthService.java
new file mode 100755
index 000000000..cdda6a3b9
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/AuthService.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.auth;
+
+/**
+ * Interface for authentication and authorization.
+ *
+ * @author Carpenter Lee
+ * @since 1.5.0
+ */
+public interface AuthService {
+
+ /**
+ * Get the authentication user.
+ *
+ * @param request the request contains the user information
+ * @return the auth user represent the current user, when the user is illegal, a null value will return.
+ */
+ AuthUser getAuthUser(R request);
+
+ /**
+ * Privilege type.
+ */
+ enum PrivilegeType {
+ /**
+ * Read rule
+ */
+ READ_RULE,
+ /**
+ * Create or modify rule
+ */
+ WRITE_RULE,
+ /**
+ * Delete rule
+ */
+ DELETE_RULE,
+ /**
+ * Read metrics
+ */
+ READ_METRIC,
+ /**
+ * Add machine
+ */
+ ADD_MACHINE,
+ /**
+ * All privileges above are granted.
+ */
+ ALL
+ }
+
+ /**
+ * Represents the current user.
+ */
+ interface AuthUser {
+
+ /**
+ * Query whether current user has the specific privilege to the target, the target
+ * may be an app name or an ip address, or other destination.
+ *
+ * This method will use return value to represent whether user has the specific
+ * privileges to the target, but to throw a RuntimeException to represent no auth
+ * is also a good way.
+ *
+ *
+ * @param target the target to check
+ * @param privilegeType the privilege type to check
+ * @return if current user has the specific privileges to the target, return true,
+ * otherwise return false.
+ */
+ boolean authTarget(String target, PrivilegeType privilegeType);
+
+ /**
+ * Check whether current user is a super-user.
+ *
+ * @return if current user is super user return true, else return false.
+ */
+ boolean isSuperUser();
+
+ /**
+ * Get current user's nick name.
+ *
+ * @return current user's nick name.
+ */
+ String getNickName();
+
+ /**
+ * Get current user's login name.
+ *
+ * @return current user's login name.
+ */
+ String getLoginName();
+
+ /**
+ * Get current user's ID.
+ *
+ * @return ID of current user
+ */
+ String getId();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/FakeAuthServiceImpl.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/FakeAuthServiceImpl.java
new file mode 100755
index 000000000..b40ea5642
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/FakeAuthServiceImpl.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.auth;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * A fake AuthService implementation, which will pass all user auth checking.
+ *
+ * @author Carpenter Lee
+ * @since 1.5.0
+ */
+@Component
+public class FakeAuthServiceImpl implements AuthService {
+
+ @Override
+ public AuthUser getAuthUser(HttpServletRequest request) {
+ return new AuthUserImpl();
+ }
+
+ static final class AuthUserImpl implements AuthUser {
+
+ @Override
+ public boolean authTarget(String target, PrivilegeType privilegeType) {
+ // fake implementation, always return true
+ return true;
+ }
+
+ @Override
+ public boolean isSuperUser() {
+ // fake implementation, always return true
+ return true;
+ }
+
+ @Override
+ public String getNickName() {
+ return "FAKE_NICK_NAME";
+ }
+
+ @Override
+ public String getLoginName() {
+ return "FAKE_LOGIN_NAME";
+ }
+
+ @Override
+ public String getId() {
+ return "FAKE_EMP_ID";
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java
new file mode 100755
index 000000000..1cae8a60d
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/auth/SimpleWebAuthServiceImpl.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.auth;
+
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @author cdfive
+ * @since 1.6.0
+ */
+@Primary
+@Component
+public class SimpleWebAuthServiceImpl implements AuthService {
+
+ public static final String WEB_SESSTION_KEY = "session_sentinel_admin";
+
+ @Override
+ public AuthUser getAuthUser(HttpServletRequest request) {
+ HttpSession session = request.getSession();
+ Object sentinelUserObj = session.getAttribute(SimpleWebAuthServiceImpl.WEB_SESSTION_KEY);
+ if (sentinelUserObj != null && sentinelUserObj instanceof AuthUser) {
+ return (AuthUser) sentinelUserObj;
+ }
+
+ return null;
+ }
+
+ public static final class SimpleWebAuthUserImpl implements AuthUser {
+
+ private String username;
+
+ public SimpleWebAuthUserImpl(String username) {
+ this.username = username;
+ }
+
+ @Override
+ public boolean authTarget(String target, PrivilegeType privilegeType) {
+ return true;
+ }
+
+ @Override
+ public boolean isSuperUser() {
+ return true;
+ }
+
+ @Override
+ public String getNickName() {
+ return username;
+ }
+
+ @Override
+ public String getLoginName() {
+ return username;
+ }
+
+ @Override
+ public String getId() {
+ return username;
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandFailedException.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandFailedException.java
new file mode 100755
index 000000000..76b6aeb10
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandFailedException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.client;
+
+/**
+ * @author Eric Zhao
+ */
+public class CommandFailedException extends RuntimeException {
+
+ public CommandFailedException() {}
+
+ public CommandFailedException(String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandNotFoundException.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandNotFoundException.java
new file mode 100755
index 000000000..0db956807
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/CommandNotFoundException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.client;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+public class CommandNotFoundException extends Exception {
+
+ public CommandNotFoundException() { }
+
+ public CommandNotFoundException(String message) {
+ super(message);
+ }
+
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
new file mode 100755
index 000000000..5db635101
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
@@ -0,0 +1,791 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.client;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
+import com.alibaba.csp.sentinel.command.CommandConstants;
+import com.alibaba.csp.sentinel.config.SentinelConfig;
+import com.alibaba.csp.sentinel.command.vo.NodeVo;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.util.AsyncUtils;
+import com.alibaba.csp.sentinel.slots.block.Rule;
+import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
+import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
+import com.alibaba.csp.sentinel.slots.system.SystemRule;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.ClusterClientInfoVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterServerStateVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterStateSimpleEntity;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ClusterClientConfig;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ServerFlowConfig;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.config.ServerTransportConfig;
+import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.concurrent.FutureCallback;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.DefaultRedirectStrategy;
+import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
+import org.apache.http.impl.nio.client.HttpAsyncClients;
+import org.apache.http.impl.nio.reactor.IOReactorConfig;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+/**
+ * Communicate with Sentinel client.
+ *
+ * @author leyou
+ */
+@Component
+public class SentinelApiClient {
+ private static Logger logger = LoggerFactory.getLogger(SentinelApiClient.class);
+
+ private static final Charset DEFAULT_CHARSET = Charset.forName(SentinelConfig.charset());
+
+ private static final String RESOURCE_URL_PATH = "jsonTree";
+ private static final String CLUSTER_NODE_PATH = "clusterNode";
+ private static final String GET_RULES_PATH = "getRules";
+ private static final String SET_RULES_PATH = "setRules";
+ private static final String GET_PARAM_RULE_PATH = "getParamFlowRules";
+ private static final String SET_PARAM_RULE_PATH = "setParamFlowRules";
+
+ private static final String FETCH_CLUSTER_MODE_PATH = "getClusterMode";
+ private static final String MODIFY_CLUSTER_MODE_PATH = "setClusterMode";
+ private static final String FETCH_CLUSTER_CLIENT_CONFIG_PATH = "cluster/client/fetchConfig";
+ private static final String MODIFY_CLUSTER_CLIENT_CONFIG_PATH = "cluster/client/modifyConfig";
+
+ private static final String FETCH_CLUSTER_SERVER_ALL_CONFIG_PATH = "cluster/server/fetchConfig";
+ private static final String FETCH_CLUSTER_SERVER_BASIC_INFO_PATH = "cluster/server/info";
+
+ private static final String MODIFY_CLUSTER_SERVER_TRANSPORT_CONFIG_PATH = "cluster/server/modifyTransportConfig";
+ private static final String MODIFY_CLUSTER_SERVER_FLOW_CONFIG_PATH = "cluster/server/modifyFlowConfig";
+ private static final String MODIFY_CLUSTER_SERVER_NAMESPACE_SET_PATH = "cluster/server/modifyNamespaceSet";
+
+ private static final String FETCH_GATEWAY_API_PATH = "gateway/getApiDefinitions";
+ private static final String MODIFY_GATEWAY_API_PATH = "gateway/updateApiDefinitions";
+
+ private static final String FETCH_GATEWAY_FLOW_RULE_PATH = "gateway/getRules";
+ private static final String MODIFY_GATEWAY_FLOW_RULE_PATH = "gateway/updateRules";
+
+ private static final String FLOW_RULE_TYPE = "flow";
+ private static final String DEGRADE_RULE_TYPE = "degrade";
+ private static final String SYSTEM_RULE_TYPE = "system";
+ private static final String AUTHORITY_TYPE = "authority";
+
+ private CloseableHttpAsyncClient httpClient;
+
+ private static final SentinelVersion version160 = new SentinelVersion(1, 6, 0);
+
+ @Autowired
+ private AppManagement appManagement;
+
+ public SentinelApiClient() {
+ IOReactorConfig ioConfig = IOReactorConfig.custom().setConnectTimeout(3000).setSoTimeout(10000)
+ .setIoThreadCount(Runtime.getRuntime().availableProcessors() * 2).build();
+ httpClient = HttpAsyncClients.custom().setRedirectStrategy(new DefaultRedirectStrategy() {
+ @Override
+ protected boolean isRedirectable(final String method) {
+ return false;
+ }
+ }).setMaxConnTotal(4000).setMaxConnPerRoute(1000).setDefaultIOReactorConfig(ioConfig).build();
+ httpClient.start();
+ }
+
+ private boolean isSuccess(int statusCode) {
+ return statusCode >= 200 && statusCode < 300;
+ }
+
+ private boolean isCommandNotFound(int statusCode, String body) {
+ return statusCode == 400 && StringUtil.isNotEmpty(body) && body.contains(CommandConstants.MSG_UNKNOWN_COMMAND_PREFIX);
+ }
+
+ private StringBuilder queryString(Map params) {
+ StringBuilder queryStringBuilder = new StringBuilder();
+ for (Entry entry : params.entrySet()) {
+ if (StringUtil.isEmpty(entry.getValue())) {
+ continue;
+ }
+ String name = urlEncode(entry.getKey());
+ String value = urlEncode(entry.getValue());
+ if (name != null && value != null) {
+ if (queryStringBuilder.length() > 0) {
+ queryStringBuilder.append('&');
+ }
+ queryStringBuilder.append(name).append('=').append(value);
+ }
+ }
+ return queryStringBuilder;
+ }
+
+ private HttpUriRequest postRequest(String url, Map params) {
+ HttpPost httpPost = new HttpPost(url);
+ if (params != null && params.size() > 0) {
+ List list = new ArrayList<>(params.size());
+ for (Entry entry : params.entrySet()) {
+ list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
+ }
+ try {
+ httpPost.setEntity(new UrlEncodedFormEntity(list));
+ } catch (UnsupportedEncodingException e) {
+ logger.warn("httpPostContent encode entity error: {}", params, e);
+ return null;
+ }
+ }
+ return httpPost;
+ }
+
+ private String urlEncode(String str) {
+ try {
+ return URLEncoder.encode(str, DEFAULT_CHARSET.name());
+ } catch (UnsupportedEncodingException e) {
+ logger.info("encode string error: {}", str, e);
+ return null;
+ }
+ }
+
+ private String getBody(HttpResponse response) throws Exception {
+ Charset charset = null;
+ try {
+ String contentTypeStr = response.getFirstHeader("Content-type").getValue();
+ if (StringUtil.isNotEmpty(contentTypeStr)) {
+ ContentType contentType = ContentType.parse(contentTypeStr);
+ charset = contentType.getCharset();
+ }
+ } catch (Exception ignore) {
+ }
+ return EntityUtils.toString(response.getEntity(), charset != null ? charset : DEFAULT_CHARSET);
+ }
+
+ /**
+ * With no param
+ *
+ * @param ip
+ * @param port
+ * @param api
+ * @return
+ */
+ private CompletableFuture executeCommand(String ip, int port, String api, boolean useHttpPost) {
+ return executeCommand(ip, port, api, null, useHttpPost);
+ }
+
+ /**
+ * No app specified, force to GET
+ *
+ * @param ip
+ * @param port
+ * @param api
+ * @param params
+ * @return
+ */
+ private CompletableFuture executeCommand(String ip, int port, String api, Map params, boolean useHttpPost) {
+ return executeCommand(null, ip, port, api, params, useHttpPost);
+ }
+
+ /**
+ * Prefer to execute request using POST
+ *
+ * @param app
+ * @param ip
+ * @param port
+ * @param api
+ * @param params
+ * @return
+ */
+ private CompletableFuture executeCommand(String app, String ip, int port, String api, Map params, boolean useHttpPost) {
+ CompletableFuture future = new CompletableFuture<>();
+ if (StringUtil.isBlank(ip) || StringUtil.isBlank(api)) {
+ future.completeExceptionally(new IllegalArgumentException("Bad URL or command name"));
+ return future;
+ }
+ StringBuilder urlBuilder = new StringBuilder();
+ urlBuilder.append("http://");
+ urlBuilder.append(ip).append(':').append(port).append('/').append(api);
+ if (params == null) {
+ params = Collections.emptyMap();
+ }
+ boolean supportPost = StringUtil.isNotEmpty(app) && Optional.ofNullable(appManagement.getDetailApp(app))
+ .flatMap(e -> e.getMachine(ip, port))
+ .flatMap(m -> VersionUtils.parseVersion(m.getVersion())
+ .map(v -> v.greaterOrEqual(version160)))
+ .orElse(false);
+ if (!useHttpPost || !supportPost) {
+ // Using GET in older versions, append parameters after url
+ if (!params.isEmpty()) {
+ if (urlBuilder.indexOf("?") == -1) {
+ urlBuilder.append('?');
+ } else {
+ urlBuilder.append('&');
+ }
+ urlBuilder.append(queryString(params));
+ }
+ return executeCommand(new HttpGet(urlBuilder.toString()));
+ } else {
+ // Using POST
+ return executeCommand(postRequest(urlBuilder.toString(), params));
+ }
+ }
+
+ private CompletableFuture executeCommand(HttpUriRequest request) {
+ CompletableFuture future = new CompletableFuture<>();
+ httpClient.execute(request, new FutureCallback() {
+ @Override
+ public void completed(final HttpResponse response) {
+ int statusCode = response.getStatusLine().getStatusCode();
+ try {
+ String value = getBody(response);
+ if (isSuccess(statusCode)) {
+ future.complete(value);
+ } else {
+ if (isCommandNotFound(statusCode, value)) {
+ future.completeExceptionally(new CommandNotFoundException(request.getURI().getPath()));
+ } else {
+ future.completeExceptionally(new CommandFailedException(value));
+ }
+ }
+
+ } catch (Exception ex) {
+ future.completeExceptionally(ex);
+ logger.error("HTTP request failed: {}", request.getURI().toString(), ex);
+ }
+ }
+
+ @Override
+ public void failed(final Exception ex) {
+ future.completeExceptionally(ex);
+ logger.error("HTTP request failed: {}", request.getURI().toString(), ex);
+ }
+
+ @Override
+ public void cancelled() {
+ future.complete(null);
+ }
+ });
+ return future;
+ }
+
+ public void close() throws Exception {
+ httpClient.close();
+ }
+
+ @Nullable
+ private CompletableFuture> fetchItemsAsync(String ip, int port, String api, String type, Class ruleType) {
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ Map params = null;
+ if (StringUtil.isNotEmpty(type)) {
+ params = new HashMap<>(1);
+ params.put("type", type);
+ }
+ return executeCommand(ip, port, api, params, false)
+ .thenApply(json -> JSON.parseArray(json, ruleType));
+ }
+
+ @Nullable
+ private List fetchItems(String ip, int port, String api, String type, Class ruleType) {
+ try {
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ Map params = null;
+ if (StringUtil.isNotEmpty(type)) {
+ params = new HashMap<>(1);
+ params.put("type", type);
+ }
+ return fetchItemsAsync(ip, port, api, type, ruleType).get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error when fetching items from api: {} -> {}", api, type, e);
+ return null;
+ } catch (Exception e) {
+ logger.error("Error when fetching items: {} -> {}", api, type, e);
+ return null;
+ }
+ }
+
+ private List fetchRules(String ip, int port, String type, Class ruleType) {
+ return fetchItems(ip, port, GET_RULES_PATH, type, ruleType);
+ }
+
+ private boolean setRules(String app, String ip, int port, String type, List extends RuleEntity> entities) {
+ if (entities == null) {
+ return true;
+ }
+ try {
+ AssertUtil.notEmpty(app, "Bad app name");
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ String data = JSON.toJSONString(
+ entities.stream().map(r -> r.toRule()).collect(Collectors.toList()));
+ Map params = new HashMap<>(2);
+ params.put("type", type);
+ params.put("data", data);
+ String result = executeCommand(app, ip, port, SET_RULES_PATH, params, true).get();
+ logger.info("setRules: {}", result);
+ return true;
+ } catch (InterruptedException | ExecutionException e) {
+ logger.warn("setRules api failed: {}", type, e);
+ return false;
+ } catch (Exception e) {
+ logger.warn("setRules failed", e);
+ return false;
+ }
+ }
+
+ public List fetchResourceOfMachine(String ip, int port, String type) {
+ return fetchItems(ip, port, RESOURCE_URL_PATH, type, NodeVo.class);
+ }
+
+ /**
+ * Fetch cluster node.
+ *
+ * @param ip ip to fetch
+ * @param port port of the ip
+ * @param includeZero whether zero value should in the result list.
+ * @return
+ */
+ public List fetchClusterNodeOfMachine(String ip, int port, boolean includeZero) {
+ String type = "noZero";
+ if (includeZero) {
+ type = "zero";
+ }
+ return fetchItems(ip, port, CLUSTER_NODE_PATH, type, NodeVo.class);
+ }
+
+ public List fetchFlowRuleOfMachine(String app, String ip, int port) {
+ List rules = fetchRules(ip, port, FLOW_RULE_TYPE, FlowRule.class);
+ if (rules != null) {
+ return rules.stream().map(rule -> FlowRuleEntity.fromFlowRule(app, ip, port, rule))
+ .collect(Collectors.toList());
+ } else {
+ return null;
+ }
+ }
+
+ public List fetchDegradeRuleOfMachine(String app, String ip, int port) {
+ List rules = fetchRules(ip, port, DEGRADE_RULE_TYPE, DegradeRule.class);
+ if (rules != null) {
+ return rules.stream().map(rule -> DegradeRuleEntity.fromDegradeRule(app, ip, port, rule))
+ .collect(Collectors.toList());
+ } else {
+ return null;
+ }
+ }
+
+ public List fetchSystemRuleOfMachine(String app, String ip, int port) {
+ List rules = fetchRules(ip, port, SYSTEM_RULE_TYPE, SystemRule.class);
+ if (rules != null) {
+ return rules.stream().map(rule -> SystemRuleEntity.fromSystemRule(app, ip, port, rule))
+ .collect(Collectors.toList());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Fetch all parameter flow rules from provided machine.
+ *
+ * @param app application name
+ * @param ip machine client IP
+ * @param port machine client port
+ * @return all retrieved parameter flow rules
+ * @since 0.2.1
+ */
+ public CompletableFuture> fetchParamFlowRulesOfMachine(String app, String ip, int port) {
+ try {
+ AssertUtil.notEmpty(app, "Bad app name");
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ return fetchItemsAsync(ip, port, GET_PARAM_RULE_PATH, null, ParamFlowRule.class)
+ .thenApply(rules -> rules.stream()
+ .map(e -> ParamFlowRuleEntity.fromAuthorityRule(app, ip, port, e))
+ .collect(Collectors.toList())
+ );
+ } catch (Exception e) {
+ logger.error("Error when fetching parameter flow rules", e);
+ return AsyncUtils.newFailedFuture(e);
+ }
+ }
+
+ /**
+ * Fetch all authority rules from provided machine.
+ *
+ * @param app application name
+ * @param ip machine client IP
+ * @param port machine client port
+ * @return all retrieved authority rules
+ * @since 0.2.1
+ */
+ public List fetchAuthorityRulesOfMachine(String app, String ip, int port) {
+ AssertUtil.notEmpty(app, "Bad app name");
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ Map params = new HashMap<>(1);
+ params.put("type", AUTHORITY_TYPE);
+ List rules = fetchRules(ip, port, AUTHORITY_TYPE, AuthorityRule.class);
+ return Optional.ofNullable(rules).map(r -> r.stream()
+ .map(e -> AuthorityRuleEntity.fromAuthorityRule(app, ip, port, e))
+ .collect(Collectors.toList())
+ ).orElse(null);
+ }
+
+ /**
+ * set rules of the machine. rules == null will return immediately;
+ * rules.isEmpty() means setting the rules to empty.
+ *
+ * @param app
+ * @param ip
+ * @param port
+ * @param rules
+ * @return whether successfully set the rules.
+ */
+ public boolean setFlowRuleOfMachine(String app, String ip, int port, List rules) {
+ return setRules(app, ip, port, FLOW_RULE_TYPE, rules);
+ }
+
+ /**
+ * set rules of the machine. rules == null will return immediately;
+ * rules.isEmpty() means setting the rules to empty.
+ *
+ * @param app
+ * @param ip
+ * @param port
+ * @param rules
+ * @return whether successfully set the rules.
+ */
+ public boolean setDegradeRuleOfMachine(String app, String ip, int port, List rules) {
+ return setRules(app, ip, port, DEGRADE_RULE_TYPE, rules);
+ }
+
+ /**
+ * set rules of the machine. rules == null will return immediately;
+ * rules.isEmpty() means setting the rules to empty.
+ *
+ * @param app
+ * @param ip
+ * @param port
+ * @param rules
+ * @return whether successfully set the rules.
+ */
+ public boolean setSystemRuleOfMachine(String app, String ip, int port, List rules) {
+ return setRules(app, ip, port, SYSTEM_RULE_TYPE, rules);
+ }
+
+ public boolean setAuthorityRuleOfMachine(String app, String ip, int port, List rules) {
+ return setRules(app, ip, port, AUTHORITY_TYPE, rules);
+ }
+
+ public CompletableFuture setParamFlowRuleOfMachine(String app, String ip, int port, List rules) {
+ if (rules == null) {
+ return CompletableFuture.completedFuture(null);
+ }
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ String data = JSON.toJSONString(
+ rules.stream().map(ParamFlowRuleEntity::getRule).collect(Collectors.toList())
+ );
+ Map params = new HashMap<>(1);
+ params.put("data", data);
+ return executeCommand(app, ip, port, SET_PARAM_RULE_PATH, params, true)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Push parameter flow rules to client failed: " + e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when setting parameter flow rule", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ // Cluster related
+
+ public CompletableFuture fetchClusterMode(String ip, int port) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ return executeCommand(ip, port, FETCH_CLUSTER_MODE_PATH, false)
+ .thenApply(r -> JSON.parseObject(r, ClusterStateSimpleEntity.class));
+ } catch (Exception ex) {
+ logger.warn("Error when fetching cluster mode", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture modifyClusterMode(String ip, int port, int mode) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ Map params = new HashMap<>(1);
+ params.put("mode", String.valueOf(mode));
+ return executeCommand(ip, port, MODIFY_CLUSTER_MODE_PATH, params, false)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Error when modifying cluster mode: " + e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when modifying cluster mode", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture fetchClusterClientInfoAndConfig(String ip, int port) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ return executeCommand(ip, port, FETCH_CLUSTER_CLIENT_CONFIG_PATH, false)
+ .thenApply(r -> JSON.parseObject(r, ClusterClientInfoVO.class));
+ } catch (Exception ex) {
+ logger.warn("Error when fetching cluster client config", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture modifyClusterClientConfig(String app, String ip, int port, ClusterClientConfig config) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ Map params = new HashMap<>(1);
+ params.put("data", JSON.toJSONString(config));
+ return executeCommand(app, ip, port, MODIFY_CLUSTER_CLIENT_CONFIG_PATH, params, true)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Error when modifying cluster client config: " + e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when modifying cluster client config", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture modifyClusterServerFlowConfig(String app, String ip, int port, ServerFlowConfig config) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ Map params = new HashMap<>(1);
+ params.put("data", JSON.toJSONString(config));
+ return executeCommand(app, ip, port, MODIFY_CLUSTER_SERVER_FLOW_CONFIG_PATH, params, true)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Error when modifying cluster server flow config: " + e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when modifying cluster server flow config", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture modifyClusterServerTransportConfig(String app, String ip, int port, ServerTransportConfig config) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ Map params = new HashMap<>(2);
+ params.put("port", config.getPort().toString());
+ params.put("idleSeconds", config.getIdleSeconds().toString());
+ return executeCommand(app, ip, port, MODIFY_CLUSTER_SERVER_TRANSPORT_CONFIG_PATH, params, false)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Error when modifying cluster server transport config: " + e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when modifying cluster server transport config", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture modifyClusterServerNamespaceSet(String app, String ip, int port, Set set) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ Map params = new HashMap<>(1);
+ params.put("data", JSON.toJSONString(set));
+ return executeCommand(app, ip, port, MODIFY_CLUSTER_SERVER_NAMESPACE_SET_PATH, params, true)
+ .thenCompose(e -> {
+ if (CommandConstants.MSG_SUCCESS.equals(e)) {
+ return CompletableFuture.completedFuture(null);
+ } else {
+ logger.warn("Error when modifying cluster server NamespaceSet", e);
+ return AsyncUtils.newFailedFuture(new RuntimeException(e));
+ }
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when modifying cluster server NamespaceSet", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture fetchClusterServerBasicInfo(String ip, int port) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+ try {
+ return executeCommand(ip, port, FETCH_CLUSTER_SERVER_BASIC_INFO_PATH, false)
+ .thenApply(r -> JSON.parseObject(r, ClusterServerStateVO.class));
+ } catch (Exception ex) {
+ logger.warn("Error when fetching cluster sever all config and basic info", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public CompletableFuture> fetchApis(String app, String ip, int port) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+
+ try {
+ return executeCommand(ip, port, FETCH_GATEWAY_API_PATH, false)
+ .thenApply(r -> {
+ List entities = JSON.parseArray(r, ApiDefinitionEntity.class);
+ if (entities != null) {
+ for (ApiDefinitionEntity entity : entities) {
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ }
+ }
+ return entities;
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when fetching gateway apis", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public boolean modifyApis(String app, String ip, int port, List apis) {
+ if (apis == null) {
+ return true;
+ }
+
+ try {
+ AssertUtil.notEmpty(app, "Bad app name");
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ String data = JSON.toJSONString(
+ apis.stream().map(r -> r.toApiDefinition()).collect(Collectors.toList()));
+ Map params = new HashMap<>(2);
+ params.put("data", data);
+ String result = executeCommand(app, ip, port, MODIFY_GATEWAY_API_PATH, params, true).get();
+ logger.info("Modify gateway apis: {}", result);
+ return true;
+ } catch (Exception e) {
+ logger.warn("Error when modifying gateway apis", e);
+ return false;
+ }
+ }
+
+ public CompletableFuture> fetchGatewayFlowRules(String app, String ip, int port) {
+ if (StringUtil.isBlank(ip) || port <= 0) {
+ return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));
+ }
+
+ try {
+ return executeCommand(ip, port, FETCH_GATEWAY_FLOW_RULE_PATH, false)
+ .thenApply(r -> {
+ List gatewayFlowRules = JSON.parseArray(r, GatewayFlowRule.class);
+ List entities = gatewayFlowRules.stream().map(rule -> GatewayFlowRuleEntity.fromGatewayFlowRule(app, ip, port, rule)).collect(Collectors.toList());
+ return entities;
+ });
+ } catch (Exception ex) {
+ logger.warn("Error when fetching gateway flow rules", ex);
+ return AsyncUtils.newFailedFuture(ex);
+ }
+ }
+
+ public boolean modifyGatewayFlowRules(String app, String ip, int port, List rules) {
+ if (rules == null) {
+ return true;
+ }
+
+ try {
+ AssertUtil.notEmpty(app, "Bad app name");
+ AssertUtil.notEmpty(ip, "Bad machine IP");
+ AssertUtil.isTrue(port > 0, "Bad machine port");
+ String data = JSON.toJSONString(
+ rules.stream().map(r -> r.toGatewayFlowRule()).collect(Collectors.toList()));
+ Map params = new HashMap<>(2);
+ params.put("data", data);
+ String result = executeCommand(app, ip, port, MODIFY_GATEWAY_FLOW_RULE_PATH, params, true).get();
+ logger.info("Modify gateway flow rules: {}", result);
+ return true;
+ } catch (Exception e) {
+ logger.warn("Error when modifying gateway apis", e);
+ return false;
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java
new file mode 100755
index 000000000..92e0608ec
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/DashboardConfig.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.config;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.NumberUtils;
+import org.springframework.lang.NonNull;
+
+/**
+ * Dashboard local config support.
+ *
+ * Dashboard supports configuration loading by several ways by order:
+ * 1. System.properties
+ * 2. Env
+ *
+ *
+ * @author jason
+ * @since 1.5.0
+ */
+public class DashboardConfig {
+
+ public static final int DEFAULT_MACHINE_HEALTHY_TIMEOUT_MS = 60_000;
+
+ /**
+ * Login username
+ */
+ public static final String CONFIG_AUTH_USERNAME = "sentinel.dashboard.auth.username";
+
+ /**
+ * Login password
+ */
+ public static final String CONFIG_AUTH_PASSWORD = "sentinel.dashboard.auth.password";
+
+ /**
+ * Hide application name in sidebar when it has no healthy machines after specific period in millisecond.
+ */
+ public static final String CONFIG_HIDE_APP_NO_MACHINE_MILLIS = "sentinel.dashboard.app.hideAppNoMachineMillis";
+ /**
+ * Remove application when it has no healthy machines after specific period in millisecond.
+ */
+ public static final String CONFIG_REMOVE_APP_NO_MACHINE_MILLIS = "sentinel.dashboard.removeAppNoMachineMillis";
+ /**
+ * Timeout
+ */
+ public static final String CONFIG_UNHEALTHY_MACHINE_MILLIS = "sentinel.dashboard.unhealthyMachineMillis";
+ /**
+ * Auto remove unhealthy machine after specific period in millisecond.
+ */
+ public static final String CONFIG_AUTO_REMOVE_MACHINE_MILLIS = "sentinel.dashboard.autoRemoveMachineMillis";
+
+ private static final ConcurrentMap cacheMap = new ConcurrentHashMap<>();
+
+ @NonNull
+ private static String getConfig(String name) {
+ // env
+ String val = System.getenv(name);
+ if (StringUtils.isNotEmpty(val)) {
+ return val;
+ }
+ // properties
+ val = System.getProperty(name);
+ if (StringUtils.isNotEmpty(val)) {
+ return val;
+ }
+ return "";
+ }
+
+ protected static String getConfigStr(String name) {
+ if (cacheMap.containsKey(name)) {
+ return (String) cacheMap.get(name);
+ }
+
+ String val = getConfig(name);
+
+ if (StringUtils.isBlank(val)) {
+ return null;
+ }
+
+ cacheMap.put(name, val);
+ return val;
+ }
+
+ protected static int getConfigInt(String name, int defaultVal, int minVal) {
+ if (cacheMap.containsKey(name)) {
+ return (int)cacheMap.get(name);
+ }
+ int val = NumberUtils.toInt(getConfig(name));
+ if (val == 0) {
+ val = defaultVal;
+ } else if (val < minVal) {
+ val = minVal;
+ }
+ cacheMap.put(name, val);
+ return val;
+ }
+
+ public static String getAuthUsername() {
+ return getConfigStr(CONFIG_AUTH_USERNAME);
+ }
+
+ public static String getAuthPassword() {
+ return getConfigStr(CONFIG_AUTH_PASSWORD);
+ }
+
+ public static int getHideAppNoMachineMillis() {
+ return getConfigInt(CONFIG_HIDE_APP_NO_MACHINE_MILLIS, 0, 60000);
+ }
+
+ public static int getRemoveAppNoMachineMillis() {
+ return getConfigInt(CONFIG_REMOVE_APP_NO_MACHINE_MILLIS, 0, 120000);
+ }
+
+ public static int getAutoRemoveMachineMillis() {
+ return getConfigInt(CONFIG_AUTO_REMOVE_MACHINE_MILLIS, 0, 300000);
+ }
+
+ public static int getUnhealthyMachineMillis() {
+ return getConfigInt(CONFIG_UNHEALTHY_MACHINE_MILLIS, DEFAULT_MACHINE_HEALTHY_TIMEOUT_MS, 30000);
+ }
+
+ public static void clearCache() {
+ cacheMap.clear();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java
new file mode 100755
index 000000000..3307fc0c0
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.config;
+
+import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
+import com.alibaba.csp.sentinel.dashboard.filter.AuthFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.servlet.Filter;
+
+/**
+ * @author leyou
+ */
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
+
+ @Autowired
+ private AuthFilter authFilter;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/**").addResourceLocations("classpath:/resources/");
+ }
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/").setViewName("forward:/index.htm");
+ }
+
+ /**
+ * Add {@link CommonFilter} to the server, this is the simplest way to use Sentinel
+ * for Web application.
+ */
+ @Bean
+ public FilterRegistrationBean sentinelFilterRegistration() {
+ FilterRegistrationBean registration = new FilterRegistrationBean<>();
+ registration.setFilter(new CommonFilter());
+ registration.addUrlPatterns("/*");
+ registration.setName("sentinelFilter");
+ registration.setOrder(1);
+
+ logger.info("Sentinel servlet CommonFilter registered");
+
+ return registration;
+ }
+
+ @Bean
+ public FilterRegistrationBean authenticationFilterRegistration() {
+ FilterRegistrationBean registration = new FilterRegistrationBean<>();
+ registration.setFilter(authFilter);
+ registration.addUrlPatterns("/*");
+ registration.setName("authenticationFilter");
+ registration.setOrder(0);
+ return registration;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java
new file mode 100755
index 000000000..635489661
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AppController.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.discovery.AppInfo;
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.MachineInfoVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Carpenter Lee
+ */
+@RestController
+@RequestMapping(value = "/app")
+public class AppController {
+
+ @Autowired
+ private AppManagement appManagement;
+
+ @GetMapping("/names.json")
+ public Result> queryApps(HttpServletRequest request) {
+ return Result.ofSuccess(appManagement.getAppNames());
+ }
+
+ @GetMapping("/briefinfos.json")
+ public Result> queryAppInfos(HttpServletRequest request) {
+ List list = new ArrayList<>(appManagement.getBriefApps());
+ Collections.sort(list, Comparator.comparing(AppInfo::getApp));
+ return Result.ofSuccess(list);
+ }
+
+ @GetMapping(value = "/{app}/machines.json")
+ public Result> getMachinesByApp(@PathVariable("app") String app) {
+ AppInfo appInfo = appManagement.getDetailApp(app);
+ if (appInfo == null) {
+ return Result.ofSuccess(null);
+ }
+ List list = new ArrayList<>(appInfo.getMachines());
+ Collections.sort(list, Comparator.comparing(MachineInfo::getApp).thenComparing(MachineInfo::getIp).thenComparingInt(MachineInfo::getPort));
+ return Result.ofSuccess(MachineInfoVo.fromMachineInfoList(list));
+ }
+
+ @RequestMapping(value = "/{app}/machine/remove.json")
+ public Result removeMachineById(
+ @PathVariable("app") String app,
+ @RequestParam(name = "ip") String ip,
+ @RequestParam(name = "port") int port) {
+ AppInfo appInfo = appManagement.getDetailApp(app);
+ if (appInfo == null) {
+ return Result.ofSuccess(null);
+ }
+ if (appManagement.removeMachine(app, ip, port)) {
+ return Result.ofSuccessMsg("success");
+ } else {
+ return Result.ofFail(1, "remove failed");
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java
new file mode 100755
index 000000000..58be6f656
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthController.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.SimpleWebAuthServiceImpl;
+import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author cdfive
+ * @since 1.6.0
+ */
+@RestController
+@RequestMapping("/auth")
+public class AuthController {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(AuthController.class);
+
+ @Value("${auth.username:sentinel}")
+ private String authUsername;
+
+ @Value("${auth.password:sentinel}")
+ private String authPassword;
+
+ @PostMapping("/login")
+ public Result login(HttpServletRequest request, String username, String password) {
+ if (StringUtils.isNotBlank(DashboardConfig.getAuthUsername())) {
+ authUsername = DashboardConfig.getAuthUsername();
+ }
+
+ if (StringUtils.isNotBlank(DashboardConfig.getAuthPassword())) {
+ authPassword = DashboardConfig.getAuthPassword();
+ }
+
+ /*
+ * If auth.username or auth.password is blank(set in application.properties or VM arguments),
+ * auth will pass, as the front side validate the input which can't be blank,
+ * so user can input any username or password(both are not blank) to login in that case.
+ */
+ if (StringUtils.isNotBlank(authUsername) && !authUsername.equals(username)
+ || StringUtils.isNotBlank(authPassword) && !authPassword.equals(password)) {
+ LOGGER.error("Login failed: Invalid username or password, username=" + username + ", password=" + password);
+ return Result.ofFail(-1, "Invalid username or password");
+ }
+
+ AuthService.AuthUser authUser = new SimpleWebAuthServiceImpl.SimpleWebAuthUserImpl(username);
+ request.getSession().setAttribute(SimpleWebAuthServiceImpl.WEB_SESSTION_KEY, authUser);
+ return Result.ofSuccess(authUser);
+ }
+
+ @RequestMapping(value = "/logout", method = RequestMethod.POST)
+ public Result logout(HttpServletRequest request) {
+ request.getSession().invalidate();
+ return Result.ofSuccess(null);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
new file mode 100755
index 000000000..2b285eff8
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/AuthorityRuleController.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+@RestController
+@RequestMapping(value = "/authority")
+public class AuthorityRuleController {
+
+ private final Logger logger = LoggerFactory.getLogger(AuthorityRuleController.class);
+
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+ @Autowired
+ private RuleRepository repository;
+
+ @Autowired
+ private AuthService authService;
+
+ @GetMapping("/rules")
+ public Result> apiQueryAllRulesForMachine(HttpServletRequest request,
+ @RequestParam String app,
+ @RequestParam String ip,
+ @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip cannot be null or empty");
+ }
+ if (port == null || port <= 0) {
+ return Result.ofFail(-1, "Invalid parameter: port");
+ }
+ try {
+ List rules = sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port);
+ rules = repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("Error when querying authority rules", throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ private Result checkEntityInternal(AuthorityRuleEntity entity) {
+ if (entity == null) {
+ return Result.ofFail(-1, "bad rule body");
+ }
+ if (StringUtil.isBlank(entity.getApp())) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getIp())) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (entity.getPort() == null || entity.getPort() <= 0) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (entity.getRule() == null) {
+ return Result.ofFail(-1, "rule can't be null");
+ }
+ if (StringUtil.isBlank(entity.getResource())) {
+ return Result.ofFail(-1, "resource name cannot be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getLimitApp())) {
+ return Result.ofFail(-1, "limitApp should be valid");
+ }
+ if (entity.getStrategy() != RuleConstant.AUTHORITY_WHITE
+ && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) {
+ return Result.ofFail(-1, "Unknown strategy (must be blacklist or whitelist)");
+ }
+ return null;
+ }
+
+ @PostMapping("/rule")
+ public Result apiAddAuthorityRule(HttpServletRequest request,
+ @RequestBody AuthorityRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ entity.setId(null);
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("Failed to add authority rule", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("Publish authority rules failed after rule add");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @PutMapping("/rule/{id}")
+ public Result apiUpdateParamFlowRule(HttpServletRequest request,
+ @PathVariable("id") Long id,
+ @RequestBody AuthorityRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+ if (id == null || id <= 0) {
+ return Result.ofFail(-1, "Invalid id");
+ }
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ entity.setId(id);
+ Date date = new Date();
+ entity.setGmtCreate(null);
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ if (entity == null) {
+ return Result.ofFail(-1, "Failed to save authority rule");
+ }
+ } catch (Throwable throwable) {
+ logger.error("Failed to save authority rule", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("Publish authority rules failed after rule update");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @DeleteMapping("/rule/{id}")
+ public Result apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id cannot be null");
+ }
+ AuthorityRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ } catch (Exception e) {
+ return Result.ofFail(-1, e.getMessage());
+ }
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.error("Publish authority rules failed after rule delete");
+ }
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
new file mode 100755
index 000000000..7733129a0
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DegradeController.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author leyou
+ */
+@Controller
+@RequestMapping(value = "/degrade", produces = MediaType.APPLICATION_JSON_VALUE)
+public class DegradeController {
+
+ private final Logger logger = LoggerFactory.getLogger(DegradeController.class);
+
+ @Autowired
+ private InMemDegradeRuleStore repository;
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+
+ @Autowired
+ private AuthService authService;
+
+ @ResponseBody
+ @RequestMapping("/rules.json")
+ public Result> queryMachineRules(HttpServletRequest request, String app, String ip, Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ try {
+ List rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
+ rules = repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("queryApps error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ @ResponseBody
+ @RequestMapping("/new.json")
+ public Result add(HttpServletRequest request,
+ String app, String ip, Integer port, String limitApp, String resource,
+ Double count, Integer timeWindow, Integer grade) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isBlank(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (StringUtil.isBlank(limitApp)) {
+ return Result.ofFail(-1, "limitApp can't be null or empty");
+ }
+ if (StringUtil.isBlank(resource)) {
+ return Result.ofFail(-1, "resource can't be null or empty");
+ }
+ if (count == null) {
+ return Result.ofFail(-1, "count can't be null");
+ }
+ if (timeWindow == null) {
+ return Result.ofFail(-1, "timeWindow can't be null");
+ }
+ if (grade == null) {
+ return Result.ofFail(-1, "grade can't be null");
+ }
+ if (grade < RuleConstant.DEGRADE_GRADE_RT || grade > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
+ return Result.ofFail(-1, "Invalid grade: " + grade);
+ }
+ DegradeRuleEntity entity = new DegradeRuleEntity();
+ entity.setApp(app.trim());
+ entity.setIp(ip.trim());
+ entity.setPort(port);
+ entity.setLimitApp(limitApp.trim());
+ entity.setResource(resource.trim());
+ entity.setCount(count);
+ entity.setTimeWindow(timeWindow);
+ entity.setGrade(grade);
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("add error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(app, ip, port)) {
+ logger.info("publish degrade rules fail after rule add");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @ResponseBody
+ @RequestMapping("/save.json")
+ public Result updateIfNotNull(HttpServletRequest request,
+ Long id, String app, String limitApp, String resource,
+ Double count, Integer timeWindow, Integer grade) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+ if (grade != null) {
+ if (grade < RuleConstant.DEGRADE_GRADE_RT || grade > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
+ return Result.ofFail(-1, "Invalid grade: " + grade);
+ }
+ }
+ DegradeRuleEntity entity = repository.findById(id);
+ if (entity == null) {
+ return Result.ofFail(-1, "id " + id + " dose not exist");
+ }
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+ if (StringUtil.isNotBlank(app)) {
+ entity.setApp(app.trim());
+ }
+
+ if (StringUtil.isNotBlank(limitApp)) {
+ entity.setLimitApp(limitApp.trim());
+ }
+ if (StringUtil.isNotBlank(resource)) {
+ entity.setResource(resource.trim());
+ }
+ if (count != null) {
+ entity.setCount(count);
+ }
+ if (timeWindow != null) {
+ entity.setTimeWindow(timeWindow);
+ }
+ if (grade != null) {
+ entity.setGrade(grade);
+ }
+ Date date = new Date();
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("save error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("publish degrade rules fail after rule update");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @ResponseBody
+ @RequestMapping("/delete.json")
+ public Result delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+
+ DegradeRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ } catch (Throwable throwable) {
+ logger.error("delete error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.info("publish degrade rules fail after rule delete");
+ }
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DemoController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DemoController.java
new file mode 100755
index 000000000..91ae67122
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/DemoController.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.csp.sentinel.Entry;
+import com.alibaba.csp.sentinel.EntryType;
+import com.alibaba.csp.sentinel.SphU;
+import com.alibaba.csp.sentinel.context.ContextUtil;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+
+@Controller
+@RequestMapping(value = "/demo", produces = MediaType.APPLICATION_JSON_VALUE)
+public class DemoController {
+
+ Logger logger = LoggerFactory.getLogger(MachineRegistryController.class);
+
+ @RequestMapping("/greeting")
+ public String greeting() {
+ return "index";
+ }
+
+ @RequestMapping("/link")
+ @ResponseBody
+ public String link() throws BlockException {
+
+ Entry entry = SphU.entry("head1", EntryType.IN);
+
+ Entry entry1 = SphU.entry("head2", EntryType.IN);
+ Entry entry2 = SphU.entry("head3", EntryType.IN);
+ Entry entry3 = SphU.entry("head4", EntryType.IN);
+
+ entry3.exit();
+ entry2.exit();
+ entry1.exit();
+ entry.exit();
+ return "successfully create a call link";
+ }
+
+ @RequestMapping("/loop")
+ @ResponseBody
+ public String loop(String name, int time) throws BlockException {
+ for (int i = 0; i < 10; i++) {
+ Thread timer = new Thread(new RunTask(name, time, false));
+ timer.setName("false");
+ timer.start();
+ }
+ return "successfully create a loop thread";
+ }
+
+ @RequestMapping("/slow")
+ @ResponseBody
+ public String slow(String name, int time) throws BlockException {
+ for (int i = 0; i < 10; i++) {
+ Thread timer = new Thread(new RunTask(name, time, true));
+ timer.setName("false");
+ timer.start();
+ }
+ return "successfully create a loop thread";
+ }
+
+ static class RunTask implements Runnable {
+ int time;
+ boolean stop = false;
+ String name;
+ boolean slow = false;
+
+ public RunTask(String name, int time, boolean slow) {
+ super();
+ this.time = time;
+ this.name = name;
+ this.slow = slow;
+ }
+
+ @Override
+ public void run() {
+ long startTime = System.currentTimeMillis();
+ ContextUtil.enter(String.valueOf(startTime));
+ while (!stop) {
+
+ long now = System.currentTimeMillis();
+ if (now - startTime > time * 1000) {
+ stop = true;
+ }
+ Entry e1 = null;
+ try {
+ e1 = SphU.entry(name);
+
+ if (slow == true) {
+ TimeUnit.MILLISECONDS.sleep(3000);
+ }
+
+ } catch (Exception e) {
+ } finally {
+ if (e1 != null) {
+ e1.exit();
+ }
+ }
+ Random random2 = new Random();
+ try {
+ TimeUnit.MILLISECONDS.sleep(random2.nextInt(200));
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+ ContextUtil.exit();
+ }
+
+ }
+
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java
new file mode 100755
index 000000000..71e5b7012
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/FlowControllerV1.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Flow rule controller.
+ *
+ * @author leyou
+ * @author Eric Zhao
+ */
+@RestController
+@RequestMapping(value = "/v1/flow")
+public class FlowControllerV1 {
+
+ private final Logger logger = LoggerFactory.getLogger(FlowControllerV1.class);
+
+ @Autowired
+ private InMemoryRuleRepositoryAdapter repository;
+ @Autowired
+ private AuthService authService;
+
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+
+ @GetMapping("/rules")
+ public Result> apiQueryMachineRules(HttpServletRequest request,
+ @RequestParam String app,
+ @RequestParam String ip,
+ @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ try {
+ List rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);
+ rules = repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("Error when querying flow rules", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ private Result checkEntityInternal(FlowRuleEntity entity) {
+ if (StringUtil.isBlank(entity.getApp())) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getIp())) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (entity.getPort() == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (StringUtil.isBlank(entity.getLimitApp())) {
+ return Result.ofFail(-1, "limitApp can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getResource())) {
+ return Result.ofFail(-1, "resource can't be null or empty");
+ }
+ if (entity.getGrade() == null) {
+ return Result.ofFail(-1, "grade can't be null");
+ }
+ if (entity.getGrade() != 0 && entity.getGrade() != 1) {
+ return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
+ }
+ if (entity.getCount() == null || entity.getCount() < 0) {
+ return Result.ofFail(-1, "count should be at lease zero");
+ }
+ if (entity.getStrategy() == null) {
+ return Result.ofFail(-1, "strategy can't be null");
+ }
+ if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {
+ return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
+ }
+ if (entity.getControlBehavior() == null) {
+ return Result.ofFail(-1, "controlBehavior can't be null");
+ }
+ int controlBehavior = entity.getControlBehavior();
+ if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {
+ return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
+ }
+ if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {
+ return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
+ }
+ if (entity.isClusterMode() && entity.getClusterConfig() == null) {
+ return Result.ofFail(-1, "cluster config should be valid");
+ }
+ return null;
+ }
+
+ @PostMapping("/rule")
+ public Result apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ entity.setId(null);
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ entity.setLimitApp(entity.getLimitApp().trim());
+ entity.setResource(entity.getResource().trim());
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("Failed to add flow rule", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.error("Publish flow rules failed after rule add");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @PutMapping("/save.json")
+ public Result updateIfNotNull(HttpServletRequest request, Long id, String app,
+ String limitApp, String resource, Integer grade,
+ Double count, Integer strategy, String refResource,
+ Integer controlBehavior, Integer warmUpPeriodSec,
+ Integer maxQueueingTimeMs) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+ FlowRuleEntity entity = repository.findById(id);
+ if (entity == null) {
+ return Result.ofFail(-1, "id " + id + " dose not exist");
+ }
+ if (StringUtil.isNotBlank(app)) {
+ entity.setApp(app.trim());
+ }
+ if (StringUtil.isNotBlank(limitApp)) {
+ entity.setLimitApp(limitApp.trim());
+ }
+ if (StringUtil.isNotBlank(resource)) {
+ entity.setResource(resource.trim());
+ }
+ if (grade != null) {
+ if (grade != 0 && grade != 1) {
+ return Result.ofFail(-1, "grade must be 0 or 1, but " + grade + " got");
+ }
+ entity.setGrade(grade);
+ }
+ if (count != null) {
+ entity.setCount(count);
+ }
+ if (strategy != null) {
+ if (strategy != 0 && strategy != 1 && strategy != 2) {
+ return Result.ofFail(-1, "strategy must be in [0, 1, 2], but " + strategy + " got");
+ }
+ entity.setStrategy(strategy);
+ if (strategy != 0) {
+ if (StringUtil.isBlank(refResource)) {
+ return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
+ }
+ entity.setRefResource(refResource.trim());
+ }
+ }
+ if (controlBehavior != null) {
+ if (controlBehavior != 0 && controlBehavior != 1 && controlBehavior != 2) {
+ return Result.ofFail(-1, "controlBehavior must be in [0, 1, 2], but " + controlBehavior + " got");
+ }
+ if (controlBehavior == 1 && warmUpPeriodSec == null) {
+ return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
+ }
+ if (controlBehavior == 2 && maxQueueingTimeMs == null) {
+ return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
+ }
+ entity.setControlBehavior(controlBehavior);
+ if (warmUpPeriodSec != null) {
+ entity.setWarmUpPeriodSec(warmUpPeriodSec);
+ }
+ if (maxQueueingTimeMs != null) {
+ entity.setMaxQueueingTimeMs(maxQueueingTimeMs);
+ }
+ }
+ Date date = new Date();
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ if (entity == null) {
+ return Result.ofFail(-1, "save entity fail");
+ }
+ } catch (Throwable throwable) {
+ logger.error("save error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("publish flow rules fail after rule update");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @DeleteMapping("/delete.json")
+ public Result delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+ FlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ } catch (Exception e) {
+ return Result.ofFail(-1, e.getMessage());
+ }
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.info("publish flow rules fail after rule delete");
+ }
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.setFlowRuleOfMachine(app, ip, port, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
new file mode 100755
index 000000000..9a9a7f76a
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineDiscovery;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/registry", produces = MediaType.APPLICATION_JSON_VALUE)
+public class MachineRegistryController {
+
+ private final Logger logger = LoggerFactory.getLogger(MachineRegistryController.class);
+
+ @Autowired
+ private AppManagement appManagement;
+
+ @ResponseBody
+ @RequestMapping("/machine")
+ public Result> receiveHeartBeat(String app, @RequestParam(value = "app_type", required = false, defaultValue = "0") Integer appType, Long version, String v, String hostname, String ip, Integer port) {
+ if (app == null) {
+ app = MachineDiscovery.UNKNOWN_APP_NAME;
+ }
+ if (ip == null) {
+ return Result.ofFail(-1, "ip can't be null");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (port == -1) {
+ logger.info("Receive heartbeat from " + ip + " but port not set yet");
+ return Result.ofFail(-1, "your port not set yet");
+ }
+ String sentinelVersion = StringUtil.isEmpty(v) ? "unknown" : v;
+ version = version == null ? System.currentTimeMillis() : version;
+ try {
+ MachineInfo machineInfo = new MachineInfo();
+ machineInfo.setApp(app);
+ machineInfo.setAppType(appType);
+ machineInfo.setHostname(hostname);
+ machineInfo.setIp(ip);
+ machineInfo.setPort(port);
+ machineInfo.setHeartbeatVersion(version);
+ machineInfo.setLastHeartbeat(System.currentTimeMillis());
+ machineInfo.setVersion(sentinelVersion);
+ appManagement.addMachine(machineInfo);
+ return Result.ofSuccessMsg("success");
+ } catch (Exception e) {
+ logger.error("Receive heartbeat error", e);
+ return Result.ofFail(-1, e.getMessage());
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MetricController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MetricController.java
new file mode 100755
index 000000000..ab90c0fc5
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MetricController.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.repository.metric.MetricsRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.MetricVo;
+
+/**
+ * @author leyou
+ */
+@Controller
+@RequestMapping(value = "/metric", produces = MediaType.APPLICATION_JSON_VALUE)
+public class MetricController {
+
+ private static Logger logger = LoggerFactory.getLogger(MetricController.class);
+
+ private static final long maxQueryIntervalMs = 1000 * 60 * 60;
+
+ @Autowired
+ private MetricsRepository metricStore;
+
+ @ResponseBody
+ @RequestMapping("/queryTopResourceMetric.json")
+ public Result> queryTopResourceMetric(final String app,
+ Integer pageIndex,
+ Integer pageSize,
+ Boolean desc,
+ Long startTime, Long endTime, String searchKey) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (pageIndex == null || pageIndex <= 0) {
+ pageIndex = 1;
+ }
+ if (pageSize == null) {
+ pageSize = 6;
+ }
+ if (pageSize >= 20) {
+ pageSize = 20;
+ }
+ if (desc == null) {
+ desc = true;
+ }
+ if (endTime == null) {
+ endTime = System.currentTimeMillis();
+ }
+ if (startTime == null) {
+ startTime = endTime - 1000 * 60 * 5;
+ }
+ if (endTime - startTime > maxQueryIntervalMs) {
+ return Result.ofFail(-1, "time intervalMs is too big, must <= 1h");
+ }
+ List resources = metricStore.listResourcesOfApp(app);
+ logger.debug("queryTopResourceMetric(), resources.size()={}", resources.size());
+
+ if (resources == null || resources.isEmpty()) {
+ return Result.ofSuccess(null);
+ }
+ if (!desc) {
+ Collections.reverse(resources);
+ }
+ if (StringUtil.isNotEmpty(searchKey)) {
+ List searched = new ArrayList<>();
+ for (String resource : resources) {
+ if (resource.contains(searchKey)) {
+ searched.add(resource);
+ }
+ }
+ resources = searched;
+ }
+ int totalPage = (resources.size() + pageSize - 1) / pageSize;
+ List topResource = new ArrayList<>();
+ if (pageIndex <= totalPage) {
+ topResource = resources.subList((pageIndex - 1) * pageSize,
+ Math.min(pageIndex * pageSize, resources.size()));
+ }
+ final Map> map = new ConcurrentHashMap<>();
+ logger.debug("topResource={}", topResource);
+ long time = System.currentTimeMillis();
+ for (final String resource : topResource) {
+ List entities = metricStore.queryByAppAndResourceBetween(
+ app, resource, startTime, endTime);
+ logger.debug("resource={}, entities.size()={}", resource, entities == null ? "null" : entities.size());
+ List vos = MetricVo.fromMetricEntities(entities, resource);
+ Iterable vosSorted = sortMetricVoAndDistinct(vos);
+ map.put(resource, vosSorted);
+ }
+ logger.debug("queryTopResourceMetric() total query time={} ms", System.currentTimeMillis() - time);
+ Map resultMap = new HashMap<>(16);
+ resultMap.put("totalCount", resources.size());
+ resultMap.put("totalPage", totalPage);
+ resultMap.put("pageIndex", pageIndex);
+ resultMap.put("pageSize", pageSize);
+
+ Map> map2 = new LinkedHashMap<>();
+ // order matters.
+ for (String identity : topResource) {
+ map2.put(identity, map.get(identity));
+ }
+ resultMap.put("metric", map2);
+ return Result.ofSuccess(resultMap);
+ }
+
+ @ResponseBody
+ @RequestMapping("/queryByAppAndResource.json")
+ public Result> queryByAppAndResource(String app, String identity, Long startTime, Long endTime) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(identity)) {
+ return Result.ofFail(-1, "identity can't be null or empty");
+ }
+ if (endTime == null) {
+ endTime = System.currentTimeMillis();
+ }
+ if (startTime == null) {
+ startTime = endTime - 1000 * 60;
+ }
+ if (endTime - startTime > maxQueryIntervalMs) {
+ return Result.ofFail(-1, "time intervalMs is too big, must <= 1h");
+ }
+ List entities = metricStore.queryByAppAndResourceBetween(
+ app, identity, startTime, endTime);
+ List vos = MetricVo.fromMetricEntities(entities, identity);
+ return Result.ofSuccess(sortMetricVoAndDistinct(vos));
+ }
+
+ private Iterable sortMetricVoAndDistinct(List vos) {
+ if (vos == null) {
+ return null;
+ }
+ Map map = new TreeMap<>();
+ for (MetricVo vo : vos) {
+ MetricVo oldVo = map.get(vo.getTimestamp());
+ if (oldVo == null || vo.getGmtCreate() > oldVo.getGmtCreate()) {
+ map.put(vo.getTimestamp(), vo);
+ }
+ }
+ return map.values();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
new file mode 100755
index 000000000..1a456488c
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ParamFlowRuleController.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
+import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+@RestController
+@RequestMapping(value = "/paramFlow")
+public class ParamFlowRuleController {
+
+ private final Logger logger = LoggerFactory.getLogger(ParamFlowRuleController.class);
+
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+ @Autowired
+ private AppManagement appManagement;
+ @Autowired
+ private RuleRepository repository;
+
+ @Autowired
+ private AuthService authService;
+
+ private boolean checkIfSupported(String app, String ip, int port) {
+ try {
+ return Optional.ofNullable(appManagement.getDetailApp(app))
+ .flatMap(e -> e.getMachine(ip, port))
+ .flatMap(m -> VersionUtils.parseVersion(m.getVersion())
+ .map(v -> v.greaterOrEqual(version020)))
+ .orElse(true);
+ // If error occurred or cannot retrieve machine info, return true.
+ } catch (Exception ex) {
+ return true;
+ }
+ }
+
+ @GetMapping("/rules")
+ public Result> apiQueryAllRulesForMachine(HttpServletRequest request,
+ @RequestParam String app,
+ @RequestParam String ip,
+ @RequestParam Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip cannot be null or empty");
+ }
+ if (port == null || port <= 0) {
+ return Result.ofFail(-1, "Invalid parameter: port");
+ }
+ if (!checkIfSupported(app, ip, port)) {
+ return unsupportedVersion();
+ }
+ try {
+ return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port)
+ .thenApply(repository::saveAll)
+ .thenApply(Result::ofSuccess)
+ .get();
+ } catch (ExecutionException ex) {
+ logger.error("Error when querying parameter flow rules", ex.getCause());
+ if (isNotSupported(ex.getCause())) {
+ return unsupportedVersion();
+ } else {
+ return Result.ofThrowable(-1, ex.getCause());
+ }
+ } catch (Throwable throwable) {
+ logger.error("Error when querying parameter flow rules", throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ private boolean isNotSupported(Throwable ex) {
+ return ex instanceof CommandNotFoundException;
+ }
+
+ @PostMapping("/rule")
+ public Result apiAddParamFlowRule(HttpServletRequest request,
+ @RequestBody ParamFlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) {
+ return unsupportedVersion();
+ }
+ entity.setId(null);
+ entity.getRule().setResource(entity.getResource().trim());
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get();
+ return Result.ofSuccess(entity);
+ } catch (ExecutionException ex) {
+ logger.error("Error when adding new parameter flow rules", ex.getCause());
+ if (isNotSupported(ex.getCause())) {
+ return unsupportedVersion();
+ } else {
+ return Result.ofThrowable(-1, ex.getCause());
+ }
+ } catch (Throwable throwable) {
+ logger.error("Error when adding new parameter flow rules", throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ private Result checkEntityInternal(ParamFlowRuleEntity entity) {
+ if (entity == null) {
+ return Result.ofFail(-1, "bad rule body");
+ }
+ if (StringUtil.isBlank(entity.getApp())) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getIp())) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (entity.getPort() == null || entity.getPort() <= 0) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (entity.getRule() == null) {
+ return Result.ofFail(-1, "rule can't be null");
+ }
+ if (StringUtil.isBlank(entity.getResource())) {
+ return Result.ofFail(-1, "resource name cannot be null or empty");
+ }
+ if (entity.getCount() < 0) {
+ return Result.ofFail(-1, "count should be valid");
+ }
+ if (entity.getGrade() != RuleConstant.FLOW_GRADE_QPS) {
+ return Result.ofFail(-1, "Unknown mode (blockGrade) for parameter flow control");
+ }
+ if (entity.getParamIdx() == null || entity.getParamIdx() < 0) {
+ return Result.ofFail(-1, "paramIdx should be valid");
+ }
+ if (entity.getDurationInSec() <= 0) {
+ return Result.ofFail(-1, "durationInSec should be valid");
+ }
+ if (entity.getControlBehavior() < 0) {
+ return Result.ofFail(-1, "controlBehavior should be valid");
+ }
+ return null;
+ }
+
+ @PutMapping("/rule/{id}")
+ public Result apiUpdateParamFlowRule(HttpServletRequest request,
+ @PathVariable("id") Long id,
+ @RequestBody ParamFlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null || id <= 0) {
+ return Result.ofFail(-1, "Invalid id");
+ }
+ ParamFlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofFail(-1, "id " + id + " does not exist");
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.WRITE_RULE);
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ if (!checkIfSupported(entity.getApp(), entity.getIp(), entity.getPort())) {
+ return unsupportedVersion();
+ }
+ entity.setId(id);
+ Date date = new Date();
+ entity.setGmtCreate(oldEntity.getGmtCreate());
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get();
+ return Result.ofSuccess(entity);
+ } catch (ExecutionException ex) {
+ logger.error("Error when updating parameter flow rules, id=" + id, ex.getCause());
+ if (isNotSupported(ex.getCause())) {
+ return unsupportedVersion();
+ } else {
+ return Result.ofThrowable(-1, ex.getCause());
+ }
+ } catch (Throwable throwable) {
+ logger.error("Error when updating parameter flow rules, id=" + id, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @DeleteMapping("/rule/{id}")
+ public Result apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id cannot be null");
+ }
+ ParamFlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get();
+ return Result.ofSuccess(id);
+ } catch (ExecutionException ex) {
+ logger.error("Error when deleting parameter flow rules", ex.getCause());
+ if (isNotSupported(ex.getCause())) {
+ return unsupportedVersion();
+ } else {
+ return Result.ofThrowable(-1, ex.getCause());
+ }
+ } catch (Throwable throwable) {
+ logger.error("Error when deleting parameter flow rules", throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ private CompletableFuture publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);
+ }
+
+ private Result unsupportedVersion() {
+ return Result.ofFail(4041,
+ "Sentinel client not supported for parameter flow control (unsupported version or dependency absent)");
+ }
+
+ private final SentinelVersion version020 = new SentinelVersion().setMinorVersion(2);
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java
new file mode 100755
index 000000000..70382c7ea
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/ResourceController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.csp.sentinel.command.vo.NodeVo;
+
+import com.alibaba.csp.sentinel.dashboard.domain.ResourceTreeNode;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.ResourceVo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Carpenter Lee
+ */
+@RestController
+@RequestMapping(value = "/resource")
+public class ResourceController {
+
+ private static Logger logger = LoggerFactory.getLogger(ResourceController.class);
+
+ @Autowired
+ private SentinelApiClient httpFetcher;
+
+ /**
+ * Fetch real time statistics info of the machine.
+ *
+ * @param ip ip to fetch
+ * @param port port of the ip
+ * @param type one of [root, default, cluster], 'root' means fetching from tree root node, 'default' means
+ * fetching from tree default node, 'cluster' means fetching from cluster node.
+ * @param searchKey key to search
+ * @return node statistics info.
+ */
+ @GetMapping("/machineResource.json")
+ public Result> fetchResourceChainListOfMachine(String ip, Integer port, String type,
+ String searchKey) {
+ if (StringUtil.isEmpty(ip) || port == null) {
+ return Result.ofFail(-1, "invalid param, give ip, port");
+ }
+ final String ROOT = "root";
+ final String DEFAULT = "default";
+ if (StringUtil.isEmpty(type)) {
+ type = ROOT;
+ }
+ if (ROOT.equalsIgnoreCase(type) || DEFAULT.equalsIgnoreCase(type)) {
+ List nodeVos = httpFetcher.fetchResourceOfMachine(ip, port, type);
+ if (nodeVos == null) {
+ return Result.ofSuccess(null);
+ }
+ ResourceTreeNode treeNode = ResourceTreeNode.fromNodeVoList(nodeVos);
+ treeNode.searchIgnoreCase(searchKey);
+ return Result.ofSuccess(ResourceVo.fromResourceTreeNode(treeNode));
+ } else {
+ // Normal (cluster node).
+ List nodeVos = httpFetcher.fetchClusterNodeOfMachine(ip, port, true);
+ if (nodeVos == null) {
+ return Result.ofSuccess(null);
+ }
+ if (StringUtil.isNotEmpty(searchKey)) {
+ nodeVos = nodeVos.stream().filter(node -> node.getResource()
+ .toLowerCase().contains(searchKey.toLowerCase()))
+ .collect(Collectors.toList());
+ }
+ return Result.ofSuccess(ResourceVo.fromNodeVoList(nodeVos));
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
new file mode 100755
index 000000000..66d29f580
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/SystemController.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author leyou(lihao)
+ */
+@RestController
+@RequestMapping("/system")
+public class SystemController {
+
+ private final Logger logger = LoggerFactory.getLogger(SystemController.class);
+
+ @Autowired
+ private RuleRepository repository;
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+ @Autowired
+ private AuthService authService;
+
+ private Result checkBasicParams(String app, String ip, Integer port) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ if (port <= 0 || port > 65535) {
+ return Result.ofFail(-1, "port should be in (0, 65535)");
+ }
+ return null;
+ }
+
+ @GetMapping("/rules.json")
+ public Result> apiQueryMachineRules(HttpServletRequest request, String app, String ip,
+ Integer port) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+
+ Result> checkResult = checkBasicParams(app, ip, port);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ try {
+ List rules = sentinelApiClient.fetchSystemRuleOfMachine(app, ip, port);
+ rules = repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("Query machine system rules error", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ private int countNotNullAndNotNegative(Number... values) {
+ int notNullCount = 0;
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] != null && values[i].doubleValue() >= 0) {
+ notNullCount++;
+ }
+ }
+ return notNullCount;
+ }
+
+ @RequestMapping("/new.json")
+ public Result apiAdd(HttpServletRequest request, String app, String ip, Integer port,
+ Double highestSystemLoad, Double highestCpuUsage, Long avgRt,
+ Long maxThread, Double qps) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.WRITE_RULE);
+
+ Result checkResult = checkBasicParams(app, ip, port);
+ if (checkResult != null) {
+ return checkResult;
+ }
+
+ int notNullCount = countNotNullAndNotNegative(highestSystemLoad, avgRt, maxThread, qps, highestCpuUsage);
+ if (notNullCount != 1) {
+ return Result.ofFail(-1, "only one of [highestSystemLoad, avgRt, maxThread, qps,highestCpuUsage] "
+ + "value must be set > 0, but " + notNullCount + " values get");
+ }
+ if (null != highestCpuUsage && highestCpuUsage > 1) {
+ return Result.ofFail(-1, "highestCpuUsage must between [0.0, 1.0]");
+ }
+ SystemRuleEntity entity = new SystemRuleEntity();
+ entity.setApp(app.trim());
+ entity.setIp(ip.trim());
+ entity.setPort(port);
+ // -1 is a fake value
+ if (null != highestSystemLoad) {
+ entity.setHighestSystemLoad(highestSystemLoad);
+ } else {
+ entity.setHighestSystemLoad(-1D);
+ }
+
+ if (null != highestCpuUsage) {
+ entity.setHighestCpuUsage(highestCpuUsage);
+ } else {
+ entity.setHighestCpuUsage(-1D);
+ }
+
+ if (avgRt != null) {
+ entity.setAvgRt(avgRt);
+ } else {
+ entity.setAvgRt(-1L);
+ }
+ if (maxThread != null) {
+ entity.setMaxThread(maxThread);
+ } else {
+ entity.setMaxThread(-1L);
+ }
+ if (qps != null) {
+ entity.setQps(qps);
+ } else {
+ entity.setQps(-1D);
+ }
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("Add SystemRule error", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(app, ip, port)) {
+ logger.warn("Publish system rules fail after rule add");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @GetMapping("/save.json")
+ public Result apiUpdateIfNotNull(HttpServletRequest request,
+ Long id, String app, Double highestSystemLoad, Double highestCpuUsage,
+ Long avgRt, Long maxThread, Double qps) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+ SystemRuleEntity entity = repository.findById(id);
+ if (entity == null) {
+ return Result.ofFail(-1, "id " + id + " dose not exist");
+ }
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+ if (StringUtil.isNotBlank(app)) {
+ entity.setApp(app.trim());
+ }
+ if (highestSystemLoad != null) {
+ if (highestSystemLoad < 0) {
+ return Result.ofFail(-1, "highestSystemLoad must >= 0");
+ }
+ entity.setHighestSystemLoad(highestSystemLoad);
+ }
+ if (highestCpuUsage != null) {
+ if (highestCpuUsage < 0) {
+ return Result.ofFail(-1, "highestCpuUsage must >= 0");
+ }
+ if (highestCpuUsage > 1) {
+ return Result.ofFail(-1, "highestCpuUsage must <= 1");
+ }
+ entity.setHighestCpuUsage(highestCpuUsage);
+ }
+ if (avgRt != null) {
+ if (avgRt < 0) {
+ return Result.ofFail(-1, "avgRt must >= 0");
+ }
+ entity.setAvgRt(avgRt);
+ }
+ if (maxThread != null) {
+ if (maxThread < 0) {
+ return Result.ofFail(-1, "maxThread must >= 0");
+ }
+ entity.setMaxThread(maxThread);
+ }
+ if (qps != null) {
+ if (qps < 0) {
+ return Result.ofFail(-1, "qps must >= 0");
+ }
+ entity.setQps(qps);
+ }
+ Date date = new Date();
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("save error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
+ logger.info("publish system rules fail after rule update");
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @RequestMapping("/delete.json")
+ public Result> delete(HttpServletRequest request, Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+ SystemRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ } catch (Throwable throwable) {
+ logger.error("delete error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.info("publish system rules fail after rule delete");
+ }
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.setSystemRuleOfMachine(app, ip, port, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterAssignController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterAssignController.java
new file mode 100755
index 000000000..dc2e14f5b
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterAssignController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller.cluster;
+
+import java.util.Collections;
+import java.util.Set;
+
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.ClusterAppFullAssignRequest;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.ClusterAppAssignResultVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.ClusterAppSingleServerAssignRequest;
+import com.alibaba.csp.sentinel.dashboard.service.ClusterAssignService;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Eric Zhao
+ * @since 1.4.1
+ */
+@RestController
+@RequestMapping("/cluster/assign")
+public class ClusterAssignController {
+
+ private final Logger logger = LoggerFactory.getLogger(ClusterAssignController.class);
+
+ @Autowired
+ private ClusterAssignService clusterAssignService;
+
+ @PostMapping("/all_server/{app}")
+ public Result apiAssignAllClusterServersOfApp(@PathVariable String app,
+ @RequestBody
+ ClusterAppFullAssignRequest assignRequest) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (assignRequest == null || assignRequest.getClusterMap() == null
+ || assignRequest.getRemainingList() == null) {
+ return Result.ofFail(-1, "bad request body");
+ }
+ try {
+ return Result.ofSuccess(clusterAssignService.applyAssignToApp(app, assignRequest.getClusterMap(),
+ assignRequest.getRemainingList()));
+ } catch (Throwable throwable) {
+ logger.error("Error when assigning full cluster servers for app: " + app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @PostMapping("/single_server/{app}")
+ public Result apiAssignSingleClusterServersOfApp(@PathVariable String app,
+ @RequestBody ClusterAppSingleServerAssignRequest assignRequest) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (assignRequest == null || assignRequest.getClusterMap() == null) {
+ return Result.ofFail(-1, "bad request body");
+ }
+ try {
+ return Result.ofSuccess(clusterAssignService.applyAssignToApp(app, Collections.singletonList(assignRequest.getClusterMap()),
+ assignRequest.getRemainingList()));
+ } catch (Throwable throwable) {
+ logger.error("Error when assigning single cluster servers for app: " + app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @PostMapping("/unbind_server/{app}")
+ public Result apiUnbindClusterServersOfApp(@PathVariable String app,
+ @RequestBody Set machineIds) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (machineIds == null || machineIds.isEmpty()) {
+ return Result.ofFail(-1, "bad request body");
+ }
+ try {
+ return Result.ofSuccess(clusterAssignService.unbindClusterServers(app, machineIds));
+ } catch (Throwable throwable) {
+ logger.error("Error when unbinding cluster server {} for app <{}>", machineIds, app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterConfigController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterConfigController.java
new file mode 100755
index 000000000..e9b9aed0e
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterConfigController.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller.cluster;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+
+import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
+import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException;
+import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.SentinelVersion;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.request.ClusterClientModifyRequest;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.request.ClusterModifyRequest;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.request.ClusterServerModifyRequest;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.AppClusterClientStateWrapVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.AppClusterServerStateWrapVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterUniversalStatePairVO;
+import com.alibaba.csp.sentinel.dashboard.domain.cluster.state.ClusterUniversalStateVO;
+import com.alibaba.csp.sentinel.dashboard.service.ClusterConfigService;
+import com.alibaba.csp.sentinel.dashboard.util.ClusterEntityUtils;
+import com.alibaba.csp.sentinel.dashboard.util.VersionUtils;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Eric Zhao
+ * @since 1.4.0
+ */
+@RestController
+@RequestMapping(value = "/cluster")
+public class ClusterConfigController {
+
+ private final Logger logger = LoggerFactory.getLogger(ClusterConfigController.class);
+
+ private final SentinelVersion version140 = new SentinelVersion().setMajorVersion(1).setMinorVersion(4);
+
+ @Autowired
+ private AppManagement appManagement;
+
+ @Autowired
+ private ClusterConfigService clusterConfigService;
+
+ @PostMapping("/config/modify_single")
+ public Result apiModifyClusterConfig(@RequestBody String payload) {
+ if (StringUtil.isBlank(payload)) {
+ return Result.ofFail(-1, "empty request body");
+ }
+ try {
+ JSONObject body = JSON.parseObject(payload);
+ if (body.containsKey(KEY_MODE)) {
+ int mode = body.getInteger(KEY_MODE);
+ switch (mode) {
+ case ClusterStateManager.CLUSTER_CLIENT:
+ ClusterClientModifyRequest data = JSON.parseObject(payload, ClusterClientModifyRequest.class);
+ Result res = checkValidRequest(data);
+ if (res != null) {
+ return res;
+ }
+ clusterConfigService.modifyClusterClientConfig(data).get();
+ return Result.ofSuccess(true);
+ case ClusterStateManager.CLUSTER_SERVER:
+ ClusterServerModifyRequest d = JSON.parseObject(payload, ClusterServerModifyRequest.class);
+ Result r = checkValidRequest(d);
+ if (r != null) {
+ return r;
+ }
+ // TODO: bad design here, should refactor!
+ clusterConfigService.modifyClusterServerConfig(d).get();
+ return Result.ofSuccess(true);
+ default:
+ return Result.ofFail(-1, "invalid mode");
+ }
+ }
+ return Result.ofFail(-1, "invalid parameter");
+ } catch (ExecutionException ex) {
+ logger.error("Error when modifying cluster config", ex.getCause());
+ return errorResponse(ex);
+ } catch (Throwable ex) {
+ logger.error("Error when modifying cluster config", ex);
+ return Result.ofFail(-1, ex.getMessage());
+ }
+ }
+
+ private Result errorResponse(ExecutionException ex) {
+ if (isNotSupported(ex.getCause())) {
+ return unsupportedVersion();
+ } else {
+ return Result.ofThrowable(-1, ex.getCause());
+ }
+ }
+
+ @GetMapping("/state_single")
+ public Result apiGetClusterState(@RequestParam String app,
+ @RequestParam String ip,
+ @RequestParam Integer port) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip cannot be null or empty");
+ }
+ if (port == null || port <= 0) {
+ return Result.ofFail(-1, "Invalid parameter: port");
+ }
+ if (!checkIfSupported(app, ip, port)) {
+ return unsupportedVersion();
+ }
+ try {
+ return clusterConfigService.getClusterUniversalState(app, ip, port)
+ .thenApply(Result::ofSuccess)
+ .get();
+ } catch (ExecutionException ex) {
+ logger.error("Error when fetching cluster state", ex.getCause());
+ return errorResponse(ex);
+ } catch (Throwable throwable) {
+ logger.error("Error when fetching cluster state", throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @GetMapping("/server_state/{app}")
+ public Result> apiGetClusterServerStateOfApp(@PathVariable String app) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ try {
+ return clusterConfigService.getClusterUniversalState(app)
+ .thenApply(ClusterEntityUtils::wrapToAppClusterServerState)
+ .thenApply(Result::ofSuccess)
+ .get();
+ } catch (ExecutionException ex) {
+ logger.error("Error when fetching cluster server state of app: " + app, ex.getCause());
+ return errorResponse(ex);
+ } catch (Throwable throwable) {
+ logger.error("Error when fetching cluster server state of app: " + app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @GetMapping("/client_state/{app}")
+ public Result> apiGetClusterClientStateOfApp(@PathVariable String app) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ try {
+ return clusterConfigService.getClusterUniversalState(app)
+ .thenApply(ClusterEntityUtils::wrapToAppClusterClientState)
+ .thenApply(Result::ofSuccess)
+ .get();
+ } catch (ExecutionException ex) {
+ logger.error("Error when fetching cluster token client state of app: " + app, ex.getCause());
+ return errorResponse(ex);
+ } catch (Throwable throwable) {
+ logger.error("Error when fetching cluster token client state of app: " + app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ @GetMapping("/state/{app}")
+ public Result> apiGetClusterStateOfApp(@PathVariable String app) {
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app cannot be null or empty");
+ }
+ try {
+ return clusterConfigService.getClusterUniversalState(app)
+ .thenApply(Result::ofSuccess)
+ .get();
+ } catch (ExecutionException ex) {
+ logger.error("Error when fetching cluster state of app: " + app, ex.getCause());
+ return errorResponse(ex);
+ } catch (Throwable throwable) {
+ logger.error("Error when fetching cluster state of app: " + app, throwable);
+ return Result.ofFail(-1, throwable.getMessage());
+ }
+ }
+
+ private boolean isNotSupported(Throwable ex) {
+ return ex instanceof CommandNotFoundException;
+ }
+
+ private boolean checkIfSupported(String app, String ip, int port) {
+ try {
+ return Optional.ofNullable(appManagement.getDetailApp(app))
+ .flatMap(e -> e.getMachine(ip, port))
+ .flatMap(m -> VersionUtils.parseVersion(m.getVersion())
+ .map(v -> v.greaterOrEqual(version140)))
+ .orElse(true);
+ // If error occurred or cannot retrieve machine info, return true.
+ } catch (Exception ex) {
+ return true;
+ }
+ }
+
+ private Result checkValidRequest(ClusterModifyRequest request) {
+ if (StringUtil.isEmpty(request.getApp())) {
+ return Result.ofFail(-1, "app cannot be empty");
+ }
+ if (StringUtil.isEmpty(request.getIp())) {
+ return Result.ofFail(-1, "ip cannot be empty");
+ }
+ if (request.getPort() == null || request.getPort() < 0) {
+ return Result.ofFail(-1, "invalid port");
+ }
+ if (request.getMode() == null || request.getMode() < 0) {
+ return Result.ofFail(-1, "invalid mode");
+ }
+ if (!checkIfSupported(request.getApp(), request.getIp(), request.getPort())) {
+ return unsupportedVersion();
+ }
+ return null;
+ }
+
+ private Result unsupportedVersion() {
+ return Result.ofFail(4041, "Sentinel client not supported for cluster flow control (unsupported version or dependency absent)");
+ }
+
+ private static final String KEY_MODE = "mode";
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java
new file mode 100755
index 000000000..378e3cc3c
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiController.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller.gateway;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiPredicateItemEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.AddApiReqVo;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.ApiPredicateItemVo;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.api.UpdateApiReqVo;
+import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemApiDefinitionStore;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
+import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
+
+/**
+ * Gateway api Controller for manage gateway api definitions.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+@RestController
+@RequestMapping(value = "/gateway/api")
+public class GatewayApiController {
+
+ private final Logger logger = LoggerFactory.getLogger(GatewayApiController.class);
+
+ @Autowired
+ private InMemApiDefinitionStore repository;
+
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+
+ @Autowired
+ private AuthService authService;
+
+ @GetMapping("/list.json")
+ public Result> queryApis(HttpServletRequest request, String app, String ip, Integer port) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, AuthService.PrivilegeType.READ_RULE);
+
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+
+ try {
+ List apis = sentinelApiClient.fetchApis(app, ip, port).get();
+ repository.saveAll(apis);
+ return Result.ofSuccess(apis);
+ } catch (Throwable throwable) {
+ logger.error("queryApis error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ @PostMapping("/new.json")
+ public Result addApi(HttpServletRequest request, @RequestBody AddApiReqVo reqVo) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ String app = reqVo.getApp();
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+
+ authUser.authTarget(app, AuthService.PrivilegeType.WRITE_RULE);
+
+ ApiDefinitionEntity entity = new ApiDefinitionEntity();
+ entity.setApp(app.trim());
+
+ String ip = reqVo.getIp();
+ if (StringUtil.isBlank(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ entity.setIp(ip.trim());
+
+ Integer port = reqVo.getPort();
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ entity.setPort(port);
+
+ // API名称
+ String apiName = reqVo.getApiName();
+ if (StringUtil.isBlank(apiName)) {
+ return Result.ofFail(-1, "apiName can't be null or empty");
+ }
+ entity.setApiName(apiName.trim());
+
+ // 匹配规则列表
+ List predicateItems = reqVo.getPredicateItems();
+ if (CollectionUtils.isEmpty(predicateItems)) {
+ return Result.ofFail(-1, "predicateItems can't empty");
+ }
+
+ List predicateItemEntities = new ArrayList<>();
+ for (ApiPredicateItemVo predicateItem : predicateItems) {
+ ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();
+
+ // 匹配模式
+ Integer matchStrategy = predicateItem.getMatchStrategy();
+ if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
+ return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
+ }
+ predicateItemEntity.setMatchStrategy(matchStrategy);
+
+ // 匹配串
+ String pattern = predicateItem.getPattern();
+ if (StringUtil.isBlank(pattern)) {
+ return Result.ofFail(-1, "pattern can't be null or empty");
+ }
+ predicateItemEntity.setPattern(pattern);
+
+ predicateItemEntities.add(predicateItemEntity);
+ }
+ entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));
+
+ // 检查API名称不能重复
+ List allApis = repository.findAllByMachine(MachineInfo.of(app.trim(), ip.trim(), port));
+ if (allApis.stream().map(o -> o.getApiName()).anyMatch(o -> o.equals(apiName.trim()))) {
+ return Result.ofFail(-1, "apiName exists: " + apiName);
+ }
+
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("add gateway api error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishApis(app, ip, port)) {
+ logger.warn("publish gateway apis fail after add");
+ }
+
+ return Result.ofSuccess(entity);
+ }
+
+ @PostMapping("/save.json")
+ public Result updateApi(HttpServletRequest request, @RequestBody UpdateApiReqVo reqVo) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ String app = reqVo.getApp();
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+
+ authUser.authTarget(app, AuthService.PrivilegeType.WRITE_RULE);
+
+ Long id = reqVo.getId();
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+
+ ApiDefinitionEntity entity = repository.findById(id);
+ if (entity == null) {
+ return Result.ofFail(-1, "api does not exist, id=" + id);
+ }
+
+ // 匹配规则列表
+ List predicateItems = reqVo.getPredicateItems();
+ if (CollectionUtils.isEmpty(predicateItems)) {
+ return Result.ofFail(-1, "predicateItems can't empty");
+ }
+
+ List predicateItemEntities = new ArrayList<>();
+ for (ApiPredicateItemVo predicateItem : predicateItems) {
+ ApiPredicateItemEntity predicateItemEntity = new ApiPredicateItemEntity();
+
+ // 匹配模式
+ int matchStrategy = predicateItem.getMatchStrategy();
+ if (!Arrays.asList(URL_MATCH_STRATEGY_EXACT, URL_MATCH_STRATEGY_PREFIX, URL_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
+ return Result.ofFail(-1, "Invalid matchStrategy: " + matchStrategy);
+ }
+ predicateItemEntity.setMatchStrategy(matchStrategy);
+
+ // 匹配串
+ String pattern = predicateItem.getPattern();
+ if (StringUtil.isBlank(pattern)) {
+ return Result.ofFail(-1, "pattern can't be null or empty");
+ }
+ predicateItemEntity.setPattern(pattern);
+
+ predicateItemEntities.add(predicateItemEntity);
+ }
+ entity.setPredicateItems(new LinkedHashSet<>(predicateItemEntities));
+
+ Date date = new Date();
+ entity.setGmtModified(date);
+
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("update gateway api error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishApis(app, entity.getIp(), entity.getPort())) {
+ logger.warn("publish gateway apis fail after update");
+ }
+
+ return Result.ofSuccess(entity);
+ }
+
+ @PostMapping("/delete.json")
+ public Result deleteApi(HttpServletRequest request, Long id) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+
+ ApiDefinitionEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+
+ authUser.authTarget(oldEntity.getApp(), AuthService.PrivilegeType.DELETE_RULE);
+
+ try {
+ repository.delete(id);
+ } catch (Throwable throwable) {
+ logger.error("delete gateway api error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.warn("publish gateway apis fail after delete");
+ }
+
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishApis(String app, String ip, Integer port) {
+ List apis = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.modifyApis(app, ip, port, apis);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java
new file mode 100755
index 000000000..7d84262fe
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleController.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller.gateway;
+
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayParamFlowItemEntity;
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.AddFlowRuleReqVo;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.GatewayParamFlowItemVo;
+import com.alibaba.csp.sentinel.dashboard.domain.vo.gateway.rule.UpdateFlowRuleReqVo;
+import com.alibaba.csp.sentinel.dashboard.repository.gateway.InMemGatewayFlowRuleStore;
+import com.alibaba.csp.sentinel.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import static com.alibaba.csp.sentinel.slots.block.RuleConstant.*;
+import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;
+import static com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity.*;
+
+/**
+ * Gateway flow rule Controller for manage gateway flow rules.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+@RestController
+@RequestMapping(value = "/gateway/flow")
+public class GatewayFlowRuleController {
+
+ private final Logger logger = LoggerFactory.getLogger(GatewayFlowRuleController.class);
+
+ @Autowired
+ private InMemGatewayFlowRuleStore repository;
+
+ @Autowired
+ private SentinelApiClient sentinelApiClient;
+
+ @Autowired
+ private AuthService authService;
+
+ @GetMapping("/list.json")
+ public Result> queryFlowRules(HttpServletRequest request, String app, String ip, Integer port) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, AuthService.PrivilegeType.READ_RULE);
+
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isEmpty(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+
+ try {
+ List rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();
+ repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("query gateway flow rules error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ @PostMapping("/new.json")
+ public Result addFlowRule(HttpServletRequest request, @RequestBody AddFlowRuleReqVo reqVo) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ String app = reqVo.getApp();
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+
+ authUser.authTarget(app, AuthService.PrivilegeType.WRITE_RULE);
+
+ GatewayFlowRuleEntity entity = new GatewayFlowRuleEntity();
+ entity.setApp(app.trim());
+
+ String ip = reqVo.getIp();
+ if (StringUtil.isBlank(ip)) {
+ return Result.ofFail(-1, "ip can't be null or empty");
+ }
+ entity.setIp(ip.trim());
+
+ Integer port = reqVo.getPort();
+ if (port == null) {
+ return Result.ofFail(-1, "port can't be null");
+ }
+ entity.setPort(port);
+
+ // API类型, Route ID或API分组
+ Integer resourceMode = reqVo.getResourceMode();
+ if (resourceMode == null) {
+ return Result.ofFail(-1, "resourceMode can't be null");
+ }
+ if (!Arrays.asList(RESOURCE_MODE_ROUTE_ID, RESOURCE_MODE_CUSTOM_API_NAME).contains(resourceMode)) {
+ return Result.ofFail(-1, "invalid resourceMode: " + resourceMode);
+ }
+ entity.setResourceMode(resourceMode);
+
+ // API名称
+ String resource = reqVo.getResource();
+ if (StringUtil.isBlank(resource)) {
+ return Result.ofFail(-1, "resource can't be null or empty");
+ }
+ entity.setResource(resource.trim());
+
+ // 针对请求属性
+ GatewayParamFlowItemVo paramItem = reqVo.getParamItem();
+ if (paramItem != null) {
+ GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
+ entity.setParamItem(itemEntity);
+
+ // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie
+ Integer parseStrategy = paramItem.getParseStrategy();
+ if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER
+ , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
+ return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy);
+ }
+ itemEntity.setParseStrategy(paramItem.getParseStrategy());
+
+ // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填
+ if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
+ // 参数名称
+ String fieldName = paramItem.getFieldName();
+ if (StringUtil.isBlank(fieldName)) {
+ return Result.ofFail(-1, "fieldName can't be null or empty");
+ }
+ itemEntity.setFieldName(paramItem.getFieldName());
+
+ String pattern = paramItem.getPattern();
+ // 如果匹配串不为空,验证匹配模式
+ if (StringUtil.isNotEmpty(pattern)) {
+ itemEntity.setPattern(pattern);
+
+ Integer matchStrategy = paramItem.getMatchStrategy();
+ if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
+ return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
+ }
+ itemEntity.setMatchStrategy(matchStrategy);
+ }
+ }
+ }
+
+ // 阈值类型 0-线程数 1-QPS
+ Integer grade = reqVo.getGrade();
+ if (grade == null) {
+ return Result.ofFail(-1, "grade can't be null");
+ }
+ if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) {
+ return Result.ofFail(-1, "invalid grade: " + grade);
+ }
+ entity.setGrade(grade);
+
+ // QPS阈值
+ Double count = reqVo.getCount();
+ if (count == null) {
+ return Result.ofFail(-1, "count can't be null");
+ }
+ if (count < 0) {
+ return Result.ofFail(-1, "count should be at lease zero");
+ }
+ entity.setCount(count);
+
+ // 间隔
+ Long interval = reqVo.getInterval();
+ if (interval == null) {
+ return Result.ofFail(-1, "interval can't be null");
+ }
+ if (interval <= 0) {
+ return Result.ofFail(-1, "interval should be greater than zero");
+ }
+ entity.setInterval(interval);
+
+ // 间隔单位
+ Integer intervalUnit = reqVo.getIntervalUnit();
+ if (intervalUnit == null) {
+ return Result.ofFail(-1, "intervalUnit can't be null");
+ }
+ if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) {
+ return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit);
+ }
+ entity.setIntervalUnit(intervalUnit);
+
+ // 流控方式 0-快速失败 2-匀速排队
+ Integer controlBehavior = reqVo.getControlBehavior();
+ if (controlBehavior == null) {
+ return Result.ofFail(-1, "controlBehavior can't be null");
+ }
+ if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) {
+ return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior);
+ }
+ entity.setControlBehavior(controlBehavior);
+
+ if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) {
+ // 0-快速失败, 则Burst size必填
+ Integer burst = reqVo.getBurst();
+ if (burst == null) {
+ return Result.ofFail(-1, "burst can't be null");
+ }
+ if (burst < 0) {
+ return Result.ofFail(-1, "invalid burst: " + burst);
+ }
+ entity.setBurst(burst);
+ } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) {
+ // 1-匀速排队, 则超时时间必填
+ Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs();
+ if (maxQueueingTimeoutMs == null) {
+ return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null");
+ }
+ if (maxQueueingTimeoutMs < 0) {
+ return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs);
+ }
+ entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs);
+ }
+
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("add gateway flow rule error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishRules(app, ip, port)) {
+ logger.warn("publish gateway flow rules fail after add");
+ }
+
+ return Result.ofSuccess(entity);
+ }
+
+ @PostMapping("/save.json")
+ public Result updateFlowRule(HttpServletRequest request, @RequestBody UpdateFlowRuleReqVo reqVo) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ String app = reqVo.getApp();
+ if (StringUtil.isBlank(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+
+ authUser.authTarget(app, AuthService.PrivilegeType.WRITE_RULE);
+
+ Long id = reqVo.getId();
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+
+ GatewayFlowRuleEntity entity = repository.findById(id);
+ if (entity == null) {
+ return Result.ofFail(-1, "gateway flow rule does not exist, id=" + id);
+ }
+
+ // 针对请求属性
+ GatewayParamFlowItemVo paramItem = reqVo.getParamItem();
+ if (paramItem != null) {
+ GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
+ entity.setParamItem(itemEntity);
+
+ // 参数属性 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie
+ Integer parseStrategy = paramItem.getParseStrategy();
+ if (!Arrays.asList(PARAM_PARSE_STRATEGY_CLIENT_IP, PARAM_PARSE_STRATEGY_HOST, PARAM_PARSE_STRATEGY_HEADER
+ , PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
+ return Result.ofFail(-1, "invalid parseStrategy: " + parseStrategy);
+ }
+ itemEntity.setParseStrategy(paramItem.getParseStrategy());
+
+ // 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填
+ if (Arrays.asList(PARAM_PARSE_STRATEGY_HEADER, PARAM_PARSE_STRATEGY_URL_PARAM, PARAM_PARSE_STRATEGY_COOKIE).contains(parseStrategy)) {
+ // 参数名称
+ String fieldName = paramItem.getFieldName();
+ if (StringUtil.isBlank(fieldName)) {
+ return Result.ofFail(-1, "fieldName can't be null or empty");
+ }
+ itemEntity.setFieldName(paramItem.getFieldName());
+
+ String pattern = paramItem.getPattern();
+ // 如果匹配串不为空,验证匹配模式
+ if (StringUtil.isNotEmpty(pattern)) {
+ itemEntity.setPattern(pattern);
+
+ Integer matchStrategy = paramItem.getMatchStrategy();
+ if (!Arrays.asList(PARAM_MATCH_STRATEGY_EXACT, PARAM_MATCH_STRATEGY_CONTAINS, PARAM_MATCH_STRATEGY_REGEX).contains(matchStrategy)) {
+ return Result.ofFail(-1, "invalid matchStrategy: " + matchStrategy);
+ }
+ itemEntity.setMatchStrategy(matchStrategy);
+ }
+ }
+ } else {
+ entity.setParamItem(null);
+ }
+
+ // 阈值类型 0-线程数 1-QPS
+ Integer grade = reqVo.getGrade();
+ if (grade == null) {
+ return Result.ofFail(-1, "grade can't be null");
+ }
+ if (!Arrays.asList(FLOW_GRADE_THREAD, FLOW_GRADE_QPS).contains(grade)) {
+ return Result.ofFail(-1, "invalid grade: " + grade);
+ }
+ entity.setGrade(grade);
+
+ // QPS阈值
+ Double count = reqVo.getCount();
+ if (count == null) {
+ return Result.ofFail(-1, "count can't be null");
+ }
+ if (count < 0) {
+ return Result.ofFail(-1, "count should be at lease zero");
+ }
+ entity.setCount(count);
+
+ // 间隔
+ Long interval = reqVo.getInterval();
+ if (interval == null) {
+ return Result.ofFail(-1, "interval can't be null");
+ }
+ if (interval <= 0) {
+ return Result.ofFail(-1, "interval should be greater than zero");
+ }
+ entity.setInterval(interval);
+
+ // 间隔单位
+ Integer intervalUnit = reqVo.getIntervalUnit();
+ if (intervalUnit == null) {
+ return Result.ofFail(-1, "intervalUnit can't be null");
+ }
+ if (!Arrays.asList(INTERVAL_UNIT_SECOND, INTERVAL_UNIT_MINUTE, INTERVAL_UNIT_HOUR, INTERVAL_UNIT_DAY).contains(intervalUnit)) {
+ return Result.ofFail(-1, "Invalid intervalUnit: " + intervalUnit);
+ }
+ entity.setIntervalUnit(intervalUnit);
+
+ // 流控方式 0-快速失败 2-匀速排队
+ Integer controlBehavior = reqVo.getControlBehavior();
+ if (controlBehavior == null) {
+ return Result.ofFail(-1, "controlBehavior can't be null");
+ }
+ if (!Arrays.asList(CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_RATE_LIMITER).contains(controlBehavior)) {
+ return Result.ofFail(-1, "invalid controlBehavior: " + controlBehavior);
+ }
+ entity.setControlBehavior(controlBehavior);
+
+ if (CONTROL_BEHAVIOR_DEFAULT == controlBehavior) {
+ // 0-快速失败, 则Burst size必填
+ Integer burst = reqVo.getBurst();
+ if (burst == null) {
+ return Result.ofFail(-1, "burst can't be null");
+ }
+ if (burst < 0) {
+ return Result.ofFail(-1, "invalid burst: " + burst);
+ }
+ entity.setBurst(burst);
+ } else if (CONTROL_BEHAVIOR_RATE_LIMITER == controlBehavior) {
+ // 2-匀速排队, 则超时时间必填
+ Integer maxQueueingTimeoutMs = reqVo.getMaxQueueingTimeoutMs();
+ if (maxQueueingTimeoutMs == null) {
+ return Result.ofFail(-1, "maxQueueingTimeoutMs can't be null");
+ }
+ if (maxQueueingTimeoutMs < 0) {
+ return Result.ofFail(-1, "invalid maxQueueingTimeoutMs: " + maxQueueingTimeoutMs);
+ }
+ entity.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs);
+ }
+
+ Date date = new Date();
+ entity.setGmtModified(date);
+
+ try {
+ entity = repository.save(entity);
+ } catch (Throwable throwable) {
+ logger.error("update gateway flow rule error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishRules(app, entity.getIp(), entity.getPort())) {
+ logger.warn("publish gateway flow rules fail after update");
+ }
+
+ return Result.ofSuccess(entity);
+ }
+
+
+ @PostMapping("/delete.json")
+ public Result deleteFlowRule(HttpServletRequest request, Long id) {
+ AuthService.AuthUser authUser = authService.getAuthUser(request);
+
+ if (id == null) {
+ return Result.ofFail(-1, "id can't be null");
+ }
+
+ GatewayFlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+
+ authUser.authTarget(oldEntity.getApp(), AuthService.PrivilegeType.DELETE_RULE);
+
+ try {
+ repository.delete(id);
+ } catch (Throwable throwable) {
+ logger.error("delete gateway flow rule error:", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+
+ if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
+ logger.warn("publish gateway flow rules fail after delete");
+ }
+
+ return Result.ofSuccess(id);
+ }
+
+ private boolean publishRules(String app, String ip, Integer port) {
+ List rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
+ return sentinelApiClient.modifyGatewayFlowRules(app, ip, port, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java
new file mode 100755
index 000000000..41aea755b
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.controller.v2;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.AuthUser;
+import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
+import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
+import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
+import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
+import com.alibaba.csp.sentinel.dashboard.domain.Result;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Flow rule controller (v2).
+ *
+ * @author Eric Zhao
+ * @since 1.4.0
+ */
+@RestController
+@RequestMapping(value = "/v2/flow")
+public class FlowControllerV2 {
+
+ private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
+
+ @Autowired
+ private InMemoryRuleRepositoryAdapter repository;
+
+ @Autowired
+ @Qualifier("flowRuleDefaultProvider")
+ private DynamicRuleProvider> ruleProvider;
+ @Autowired
+ @Qualifier("flowRuleDefaultPublisher")
+ private DynamicRulePublisher> rulePublisher;
+
+ @Autowired
+ private AuthService authService;
+
+ @GetMapping("/rules")
+ public Result> apiQueryMachineRules(HttpServletRequest request, @RequestParam String app) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(app, PrivilegeType.READ_RULE);
+
+ if (StringUtil.isEmpty(app)) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ try {
+ List rules = ruleProvider.getRules(app);
+ if (rules != null && !rules.isEmpty()) {
+ for (FlowRuleEntity entity : rules) {
+ entity.setApp(app);
+ if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
+ entity.setId(entity.getClusterConfig().getFlowId());
+ }
+ }
+ }
+ rules = repository.saveAll(rules);
+ return Result.ofSuccess(rules);
+ } catch (Throwable throwable) {
+ logger.error("Error when querying flow rules", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ }
+
+ private Result checkEntityInternal(FlowRuleEntity entity) {
+ if (entity == null) {
+ return Result.ofFail(-1, "invalid body");
+ }
+ if (StringUtil.isBlank(entity.getApp())) {
+ return Result.ofFail(-1, "app can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getLimitApp())) {
+ return Result.ofFail(-1, "limitApp can't be null or empty");
+ }
+ if (StringUtil.isBlank(entity.getResource())) {
+ return Result.ofFail(-1, "resource can't be null or empty");
+ }
+ if (entity.getGrade() == null) {
+ return Result.ofFail(-1, "grade can't be null");
+ }
+ if (entity.getGrade() != 0 && entity.getGrade() != 1) {
+ return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
+ }
+ if (entity.getCount() == null || entity.getCount() < 0) {
+ return Result.ofFail(-1, "count should be at lease zero");
+ }
+ if (entity.getStrategy() == null) {
+ return Result.ofFail(-1, "strategy can't be null");
+ }
+ if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {
+ return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
+ }
+ if (entity.getControlBehavior() == null) {
+ return Result.ofFail(-1, "controlBehavior can't be null");
+ }
+ int controlBehavior = entity.getControlBehavior();
+ if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {
+ return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
+ }
+ if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {
+ return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
+ }
+ if (entity.isClusterMode() && entity.getClusterConfig() == null) {
+ return Result.ofFail(-1, "cluster config should be valid");
+ }
+ return null;
+ }
+
+ @PostMapping("/rule")
+ public Result apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE);
+
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+ entity.setId(null);
+ Date date = new Date();
+ entity.setGmtCreate(date);
+ entity.setGmtModified(date);
+ entity.setLimitApp(entity.getLimitApp().trim());
+ entity.setResource(entity.getResource().trim());
+ try {
+ entity = repository.save(entity);
+ publishRules(entity.getApp());
+ } catch (Throwable throwable) {
+ logger.error("Failed to add flow rule", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @PutMapping("/rule/{id}")
+ public Result apiUpdateFlowRule(HttpServletRequest request,
+ @PathVariable("id") Long id,
+ @RequestBody FlowRuleEntity entity) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null || id <= 0) {
+ return Result.ofFail(-1, "Invalid id");
+ }
+ FlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofFail(-1, "id " + id + " does not exist");
+ }
+ if (entity == null) {
+ return Result.ofFail(-1, "invalid body");
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.WRITE_RULE);
+
+ entity.setApp(oldEntity.getApp());
+ entity.setIp(oldEntity.getIp());
+ entity.setPort(oldEntity.getPort());
+ Result checkResult = checkEntityInternal(entity);
+ if (checkResult != null) {
+ return checkResult;
+ }
+
+ entity.setId(id);
+ Date date = new Date();
+ entity.setGmtCreate(oldEntity.getGmtCreate());
+ entity.setGmtModified(date);
+ try {
+ entity = repository.save(entity);
+ if (entity == null) {
+ return Result.ofFail(-1, "save entity fail");
+ }
+ publishRules(oldEntity.getApp());
+ } catch (Throwable throwable) {
+ logger.error("Failed to update flow rule", throwable);
+ return Result.ofThrowable(-1, throwable);
+ }
+ return Result.ofSuccess(entity);
+ }
+
+ @DeleteMapping("/rule/{id}")
+ public Result apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) {
+ AuthUser authUser = authService.getAuthUser(request);
+ if (id == null || id <= 0) {
+ return Result.ofFail(-1, "Invalid id");
+ }
+ FlowRuleEntity oldEntity = repository.findById(id);
+ if (oldEntity == null) {
+ return Result.ofSuccess(null);
+ }
+ authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE);
+ try {
+ repository.delete(id);
+ publishRules(oldEntity.getApp());
+ } catch (Exception e) {
+ return Result.ofFail(-1, e.getMessage());
+ }
+ return Result.ofSuccess(id);
+ }
+
+ private void publishRules(/*@NonNull*/ String app) throws Exception {
+ List rules = repository.findAllByApp(app);
+ rulePublisher.publish(app, rules);
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java
new file mode 100755
index 000000000..44c10daaf
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/ApplicationEntity.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.dashboard.discovery.AppInfo;
+
+/**
+ * @author leyou
+ */
+public class ApplicationEntity {
+
+ private Long id;
+ private Date gmtCreate;
+ private Date gmtModified;
+ private String app;
+ private Integer appType;
+ private String activeConsole;
+ private Date lastFetch;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public Integer getAppType() {
+ return appType;
+ }
+
+ public void setAppType(Integer appType) {
+ this.appType = appType;
+ }
+
+ public String getActiveConsole() {
+ return activeConsole;
+ }
+
+ public Date getLastFetch() {
+ return lastFetch;
+ }
+
+ public void setLastFetch(Date lastFetch) {
+ this.lastFetch = lastFetch;
+ }
+
+ public void setActiveConsole(String activeConsole) {
+ this.activeConsole = activeConsole;
+ }
+
+ public AppInfo toAppInfo() {
+ return new AppInfo(app, appType);
+ }
+
+ @Override
+ public String toString() {
+ return "ApplicationEntity{" +
+ "id=" + id +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", app='" + app + '\'' +
+ ", activeConsole='" + activeConsole + '\'' +
+ ", lastFetch=" + lastFetch +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java
new file mode 100755
index 000000000..5b91f3399
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MachineEntity.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
+
+/**
+ * @author leyou
+ */
+public class MachineEntity {
+ private Long id;
+ private Date gmtCreate;
+ private Date gmtModified;
+ private String app;
+ private String ip;
+ private String hostname;
+ private Date timestamp;
+ private Integer port;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ public MachineInfo toMachineInfo() {
+ MachineInfo machineInfo = new MachineInfo();
+
+ machineInfo.setApp(app);
+ machineInfo.setHostname(hostname);
+ machineInfo.setIp(ip);
+ machineInfo.setPort(port);
+ machineInfo.setLastHeartbeat(timestamp.getTime());
+ machineInfo.setHeartbeatVersion(timestamp.getTime());
+
+ return machineInfo;
+ }
+
+ @Override
+ public String toString() {
+ return "MachineEntity{" +
+ "id=" + id +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", app='" + app + '\'' +
+ ", ip='" + ip + '\'' +
+ ", hostname='" + hostname + '\'' +
+ ", timestamp=" + timestamp +
+ ", port=" + port +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricEntity.java
new file mode 100755
index 000000000..f08a41a69
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricEntity.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity;
+
+import java.util.Date;
+
+/**
+ * @author leyou
+ */
+public class MetricEntity {
+ private Long id;
+ private Date gmtCreate;
+ private Date gmtModified;
+ private String app;
+ /**
+ * 监控信息的时间戳
+ */
+ private Date timestamp;
+ private String resource;
+ private Long passQps;
+ private Long successQps;
+ private Long blockQps;
+ private Long exceptionQps;
+
+ /**
+ * summary rt of all success exit qps.
+ */
+ private double rt;
+
+ /**
+ * 本次聚合的总条数
+ */
+ private int count;
+
+ private int resourceCode;
+
+ public static MetricEntity copyOf(MetricEntity oldEntity) {
+ MetricEntity entity = new MetricEntity();
+ entity.setId(oldEntity.getId());
+ entity.setGmtCreate(oldEntity.getGmtCreate());
+ entity.setGmtModified(oldEntity.getGmtModified());
+ entity.setApp(oldEntity.getApp());
+ entity.setTimestamp(oldEntity.getTimestamp());
+ entity.setResource(oldEntity.getResource());
+ entity.setPassQps(oldEntity.getPassQps());
+ entity.setBlockQps(oldEntity.getBlockQps());
+ entity.setSuccessQps(oldEntity.getSuccessQps());
+ entity.setExceptionQps(oldEntity.getExceptionQps());
+ entity.setRt(oldEntity.getRt());
+ entity.setCount(oldEntity.getCount());
+ entity.setResource(oldEntity.getResource());
+ return entity;
+ }
+
+ public synchronized void addPassQps(Long passQps) {
+ this.passQps += passQps;
+ }
+
+ public synchronized void addBlockQps(Long blockQps) {
+ this.blockQps += blockQps;
+ }
+
+ public synchronized void addExceptionQps(Long exceptionQps) {
+ this.exceptionQps += exceptionQps;
+ }
+
+ public synchronized void addCount(int count) {
+ this.count += count;
+ }
+
+ public synchronized void addRtAndSuccessQps(double avgRt, Long successQps) {
+ this.rt += avgRt * successQps;
+ this.successQps += successQps;
+ }
+
+ /**
+ * {@link #rt} = {@code avgRt * successQps}
+ *
+ * @param avgRt average rt of {@code successQps}
+ * @param successQps
+ */
+ public synchronized void setRtAndSuccessQps(double avgRt, Long successQps) {
+ this.rt = avgRt * successQps;
+ this.successQps = successQps;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ this.resourceCode = resource.hashCode();
+ }
+
+ public Long getPassQps() {
+ return passQps;
+ }
+
+ public void setPassQps(Long passQps) {
+ this.passQps = passQps;
+ }
+
+ public Long getBlockQps() {
+ return blockQps;
+ }
+
+ public void setBlockQps(Long blockQps) {
+ this.blockQps = blockQps;
+ }
+
+ public Long getExceptionQps() {
+ return exceptionQps;
+ }
+
+ public void setExceptionQps(Long exceptionQps) {
+ this.exceptionQps = exceptionQps;
+ }
+
+ public double getRt() {
+ return rt;
+ }
+
+ public void setRt(double rt) {
+ this.rt = rt;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public int getResourceCode() {
+ return resourceCode;
+ }
+
+ public Long getSuccessQps() {
+ return successQps;
+ }
+
+ public void setSuccessQps(Long successQps) {
+ this.successQps = successQps;
+ }
+
+ @Override
+ public String toString() {
+ return "MetricEntity{" +
+ "id=" + id +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", app='" + app + '\'' +
+ ", timestamp=" + timestamp +
+ ", resource='" + resource + '\'' +
+ ", passQps=" + passQps +
+ ", blockQps=" + blockQps +
+ ", successQps=" + successQps +
+ ", exceptionQps=" + exceptionQps +
+ ", rt=" + rt +
+ ", count=" + count +
+ ", resourceCode=" + resourceCode +
+ '}';
+ }
+
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricPositionEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricPositionEntity.java
new file mode 100755
index 000000000..2be29eb83
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricPositionEntity.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity;
+
+import java.util.Date;
+
+/**
+ * @author leyou
+ */
+public class MetricPositionEntity {
+ private long id;
+ private Date gmtCreate;
+ private Date gmtModified;
+ private String app;
+ private String ip;
+ /**
+ * Sentinel在该应用上使用的端口
+ */
+ private int port;
+
+ /**
+ * 机器名,冗余字段
+ */
+ private String hostname;
+
+ /**
+ * 上一次拉取的最晚时间戳
+ */
+ private Date lastFetch;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public Date getLastFetch() {
+ return lastFetch;
+ }
+
+ public void setLastFetch(Date lastFetch) {
+ this.lastFetch = lastFetch;
+ }
+
+ @Override
+ public String toString() {
+ return "MetricPositionEntity{" +
+ "id=" + id +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", app='" + app + '\'' +
+ ", ip='" + ip + '\'' +
+ ", port=" + port +
+ ", hostname='" + hostname + '\'' +
+ ", lastFetch=" + lastFetch +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/SentinelVersion.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/SentinelVersion.java
new file mode 100755
index 000000000..08fcaf252
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/SentinelVersion.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+public class SentinelVersion {
+ private int majorVersion;
+ private int minorVersion;
+ private int fixVersion;
+ private String postfix;
+
+ public SentinelVersion() {
+ this(0, 0, 0);
+ }
+
+ public SentinelVersion(int major, int minor, int fix) {
+ this(major, minor, fix, null);
+ }
+
+ public SentinelVersion(int major, int minor, int fix, String postfix) {
+ this.majorVersion = major;
+ this.minorVersion = minor;
+ this.fixVersion = fix;
+ this.postfix = postfix;
+ }
+
+ /**
+ * 000, 000, 000
+ */
+ public int getFullVersion() {
+ return majorVersion * 1000000 + minorVersion * 1000 + fixVersion;
+ }
+
+ public int getMajorVersion() {
+ return majorVersion;
+ }
+
+ public SentinelVersion setMajorVersion(int majorVersion) {
+ this.majorVersion = majorVersion;
+ return this;
+ }
+
+ public int getMinorVersion() {
+ return minorVersion;
+ }
+
+ public SentinelVersion setMinorVersion(int minorVersion) {
+ this.minorVersion = minorVersion;
+ return this;
+ }
+
+ public int getFixVersion() {
+ return fixVersion;
+ }
+
+ public SentinelVersion setFixVersion(int fixVersion) {
+ this.fixVersion = fixVersion;
+ return this;
+ }
+
+ public String getPostfix() {
+ return postfix;
+ }
+
+ public SentinelVersion setPostfix(String postfix) {
+ this.postfix = postfix;
+ return this;
+ }
+
+ public boolean greaterThan(SentinelVersion version) {
+ if (version == null) {
+ return true;
+ }
+ return getFullVersion() > version.getFullVersion();
+ }
+
+ public boolean greaterOrEqual(SentinelVersion version) {
+ if (version == null) {
+ return true;
+ }
+ return getFullVersion() >= version.getFullVersion();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+
+ SentinelVersion that = (SentinelVersion)o;
+
+ if (getFullVersion() != that.getFullVersion()) { return false; }
+ return postfix != null ? postfix.equals(that.postfix) : that.postfix == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = majorVersion;
+ result = 31 * result + minorVersion;
+ result = 31 * result + fixVersion;
+ result = 31 * result + (postfix != null ? postfix.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "SentinelVersion{" +
+ "majorVersion=" + majorVersion +
+ ", minorVersion=" + minorVersion +
+ ", fixVersion=" + fixVersion +
+ ", postfix='" + postfix + '\'' +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiDefinitionEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiDefinitionEntity.java
new file mode 100755
index 000000000..b042e0ada
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiDefinitionEntity.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.gateway;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
+import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
+import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity;
+import com.alibaba.csp.sentinel.slots.block.Rule;
+
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Entity for {@link ApiDefinition}.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+public class ApiDefinitionEntity implements RuleEntity {
+
+ private Long id;
+ private String app;
+ private String ip;
+ private Integer port;
+
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ private String apiName;
+ private Set predicateItems;
+
+ public static ApiDefinitionEntity fromApiDefinition(String app, String ip, Integer port, ApiDefinition apiDefinition) {
+ ApiDefinitionEntity entity = new ApiDefinitionEntity();
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ entity.setApiName(apiDefinition.getApiName());
+
+ Set predicateItems = new LinkedHashSet<>();
+ entity.setPredicateItems(predicateItems);
+
+ Set apiPredicateItems = apiDefinition.getPredicateItems();
+ if (apiPredicateItems != null) {
+ for (ApiPredicateItem apiPredicateItem : apiPredicateItems) {
+ ApiPredicateItemEntity itemEntity = new ApiPredicateItemEntity();
+ predicateItems.add(itemEntity);
+ ApiPathPredicateItem pathPredicateItem = (ApiPathPredicateItem) apiPredicateItem;
+ itemEntity.setPattern(pathPredicateItem.getPattern());
+ itemEntity.setMatchStrategy(pathPredicateItem.getMatchStrategy());
+ }
+ }
+
+ return entity;
+ }
+
+ public ApiDefinition toApiDefinition() {
+ ApiDefinition apiDefinition = new ApiDefinition();
+ apiDefinition.setApiName(apiName);
+
+ Set apiPredicateItems = new LinkedHashSet<>();
+ apiDefinition.setPredicateItems(apiPredicateItems);
+
+ if (predicateItems != null) {
+ for (ApiPredicateItemEntity predicateItem : predicateItems) {
+ ApiPathPredicateItem apiPredicateItem = new ApiPathPredicateItem();
+ apiPredicateItems.add(apiPredicateItem);
+ apiPredicateItem.setMatchStrategy(predicateItem.getMatchStrategy());
+ apiPredicateItem.setPattern(predicateItem.getPattern());
+ }
+ }
+
+ return apiDefinition;
+ }
+
+ public ApiDefinitionEntity() {
+
+ }
+
+ public ApiDefinitionEntity(String apiName, Set predicateItems) {
+ this.apiName = apiName;
+ this.predicateItems = predicateItems;
+ }
+
+ public String getApiName() {
+ return apiName;
+ }
+
+ public void setApiName(String apiName) {
+ this.apiName = apiName;
+ }
+
+ public Set getPredicateItems() {
+ return predicateItems;
+ }
+
+ public void setPredicateItems(Set predicateItems) {
+ this.predicateItems = predicateItems;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ @Override
+ public Rule toRule() {
+ return null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+ ApiDefinitionEntity entity = (ApiDefinitionEntity) o;
+ return Objects.equals(id, entity.id) &&
+ Objects.equals(app, entity.app) &&
+ Objects.equals(ip, entity.ip) &&
+ Objects.equals(port, entity.port) &&
+ Objects.equals(gmtCreate, entity.gmtCreate) &&
+ Objects.equals(gmtModified, entity.gmtModified) &&
+ Objects.equals(apiName, entity.apiName) &&
+ Objects.equals(predicateItems, entity.predicateItems);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, app, ip, port, gmtCreate, gmtModified, apiName, predicateItems);
+ }
+
+ @Override
+ public String toString() {
+ return "ApiDefinitionEntity{" +
+ "id=" + id +
+ ", app='" + app + '\'' +
+ ", ip='" + ip + '\'' +
+ ", port=" + port +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", apiName='" + apiName + '\'' +
+ ", predicateItems=" + predicateItems +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiPredicateItemEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiPredicateItemEntity.java
new file mode 100755
index 000000000..1d6058cd0
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/ApiPredicateItemEntity.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.gateway;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
+
+import java.util.Objects;
+
+/**
+ * Entity for {@link ApiPredicateItem}.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+public class ApiPredicateItemEntity {
+
+ private String pattern;
+
+ private Integer matchStrategy;
+
+ public ApiPredicateItemEntity() {
+ }
+
+ public ApiPredicateItemEntity(String pattern, int matchStrategy) {
+ this.pattern = pattern;
+ this.matchStrategy = matchStrategy;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public Integer getMatchStrategy() {
+ return matchStrategy;
+ }
+
+ public void setMatchStrategy(Integer matchStrategy) {
+ this.matchStrategy = matchStrategy;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+ ApiPredicateItemEntity that = (ApiPredicateItemEntity) o;
+ return Objects.equals(pattern, that.pattern) &&
+ Objects.equals(matchStrategy, that.matchStrategy);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(pattern, matchStrategy);
+ }
+
+ @Override
+ public String toString() {
+ return "ApiPredicateItemEntity{" +
+ "pattern='" + pattern + '\'' +
+ ", matchStrategy=" + matchStrategy +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayFlowRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayFlowRuleEntity.java
new file mode 100755
index 000000000..391ea41f1
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayFlowRuleEntity.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.gateway;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
+import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
+import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity;
+import com.alibaba.csp.sentinel.slots.block.Rule;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * Entity for {@link GatewayFlowRule}.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+public class GatewayFlowRuleEntity implements RuleEntity {
+
+ /**间隔单位*/
+ /**0-秒*/
+ public static final int INTERVAL_UNIT_SECOND = 0;
+ /**1-分*/
+ public static final int INTERVAL_UNIT_MINUTE = 1;
+ /**2-时*/
+ public static final int INTERVAL_UNIT_HOUR = 2;
+ /**3-天*/
+ public static final int INTERVAL_UNIT_DAY = 3;
+
+ private Long id;
+ private String app;
+ private String ip;
+ private Integer port;
+
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ private String resource;
+ private Integer resourceMode;
+
+ private Integer grade;
+ private Double count;
+ private Long interval;
+ private Integer intervalUnit;
+
+ private Integer controlBehavior;
+ private Integer burst;
+
+ private Integer maxQueueingTimeoutMs;
+
+ private GatewayParamFlowItemEntity paramItem;
+
+ public static Long calIntervalSec(Long interval, Integer intervalUnit) {
+ switch (intervalUnit) {
+ case INTERVAL_UNIT_SECOND:
+ return interval;
+ case INTERVAL_UNIT_MINUTE:
+ return interval * 60;
+ case INTERVAL_UNIT_HOUR:
+ return interval * 60 * 60;
+ case INTERVAL_UNIT_DAY:
+ return interval * 60 * 60 * 24;
+ default:
+ break;
+ }
+
+ throw new IllegalArgumentException("Invalid intervalUnit: " + intervalUnit);
+ }
+
+ public static Object[] parseIntervalSec(Long intervalSec) {
+ if (intervalSec % (60 * 60 * 24) == 0) {
+ return new Object[] {intervalSec / (60 * 60 * 24), INTERVAL_UNIT_DAY};
+ }
+
+ if (intervalSec % (60 * 60 ) == 0) {
+ return new Object[] {intervalSec / (60 * 60), INTERVAL_UNIT_HOUR};
+ }
+
+ if (intervalSec % 60 == 0) {
+ return new Object[] {intervalSec / 60, INTERVAL_UNIT_MINUTE};
+ }
+
+ return new Object[] {intervalSec, INTERVAL_UNIT_SECOND};
+ }
+
+ public GatewayFlowRule toGatewayFlowRule() {
+ GatewayFlowRule rule = new GatewayFlowRule();
+ rule.setResource(resource);
+ rule.setResourceMode(resourceMode);
+
+ rule.setGrade(grade);
+ rule.setCount(count);
+ rule.setIntervalSec(calIntervalSec(interval, intervalUnit));
+
+ rule.setControlBehavior(controlBehavior);
+
+ if (burst != null) {
+ rule.setBurst(burst);
+ }
+
+ if (maxQueueingTimeoutMs != null) {
+ rule.setMaxQueueingTimeoutMs(maxQueueingTimeoutMs);
+ }
+
+ if (paramItem != null) {
+ GatewayParamFlowItem ruleItem = new GatewayParamFlowItem();
+ rule.setParamItem(ruleItem);
+ ruleItem.setParseStrategy(paramItem.getParseStrategy());
+ ruleItem.setFieldName(paramItem.getFieldName());
+ ruleItem.setPattern(paramItem.getPattern());
+
+ if (paramItem.getMatchStrategy() != null) {
+ ruleItem.setMatchStrategy(paramItem.getMatchStrategy());
+ }
+ }
+
+ return rule;
+ }
+
+ public static GatewayFlowRuleEntity fromGatewayFlowRule(String app, String ip, Integer port, GatewayFlowRule rule) {
+ GatewayFlowRuleEntity entity = new GatewayFlowRuleEntity();
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+
+ entity.setResource(rule.getResource());
+ entity.setResourceMode(rule.getResourceMode());
+
+ entity.setGrade(rule.getGrade());
+ entity.setCount(rule.getCount());
+ Object[] intervalSecResult = parseIntervalSec(rule.getIntervalSec());
+ entity.setInterval((Long) intervalSecResult[0]);
+ entity.setIntervalUnit((Integer) intervalSecResult[1]);
+
+ entity.setControlBehavior(rule.getControlBehavior());
+ entity.setBurst(rule.getBurst());
+ entity.setMaxQueueingTimeoutMs(rule.getMaxQueueingTimeoutMs());
+
+ GatewayParamFlowItem paramItem = rule.getParamItem();
+ if (paramItem != null) {
+ GatewayParamFlowItemEntity itemEntity = new GatewayParamFlowItemEntity();
+ entity.setParamItem(itemEntity);
+ itemEntity.setParseStrategy(paramItem.getParseStrategy());
+ itemEntity.setFieldName(paramItem.getFieldName());
+ itemEntity.setPattern(paramItem.getPattern());
+ itemEntity.setMatchStrategy(paramItem.getMatchStrategy());
+ }
+
+ return entity;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ @Override
+ public Rule toRule() {
+ return null;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ public GatewayParamFlowItemEntity getParamItem() {
+ return paramItem;
+ }
+
+ public void setParamItem(GatewayParamFlowItemEntity paramItem) {
+ this.paramItem = paramItem;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public Integer getResourceMode() {
+ return resourceMode;
+ }
+
+ public void setResourceMode(Integer resourceMode) {
+ this.resourceMode = resourceMode;
+ }
+
+ public Integer getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Integer grade) {
+ this.grade = grade;
+ }
+
+ public Double getCount() {
+ return count;
+ }
+
+ public void setCount(Double count) {
+ this.count = count;
+ }
+
+ public Long getInterval() {
+ return interval;
+ }
+
+ public void setInterval(Long interval) {
+ this.interval = interval;
+ }
+
+ public Integer getIntervalUnit() {
+ return intervalUnit;
+ }
+
+ public void setIntervalUnit(Integer intervalUnit) {
+ this.intervalUnit = intervalUnit;
+ }
+
+ public Integer getControlBehavior() {
+ return controlBehavior;
+ }
+
+ public void setControlBehavior(Integer controlBehavior) {
+ this.controlBehavior = controlBehavior;
+ }
+
+ public Integer getBurst() {
+ return burst;
+ }
+
+ public void setBurst(Integer burst) {
+ this.burst = burst;
+ }
+
+ public Integer getMaxQueueingTimeoutMs() {
+ return maxQueueingTimeoutMs;
+ }
+
+ public void setMaxQueueingTimeoutMs(Integer maxQueueingTimeoutMs) {
+ this.maxQueueingTimeoutMs = maxQueueingTimeoutMs;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+ GatewayFlowRuleEntity that = (GatewayFlowRuleEntity) o;
+ return Objects.equals(id, that.id) &&
+ Objects.equals(app, that.app) &&
+ Objects.equals(ip, that.ip) &&
+ Objects.equals(port, that.port) &&
+ Objects.equals(gmtCreate, that.gmtCreate) &&
+ Objects.equals(gmtModified, that.gmtModified) &&
+ Objects.equals(resource, that.resource) &&
+ Objects.equals(resourceMode, that.resourceMode) &&
+ Objects.equals(grade, that.grade) &&
+ Objects.equals(count, that.count) &&
+ Objects.equals(interval, that.interval) &&
+ Objects.equals(intervalUnit, that.intervalUnit) &&
+ Objects.equals(controlBehavior, that.controlBehavior) &&
+ Objects.equals(burst, that.burst) &&
+ Objects.equals(maxQueueingTimeoutMs, that.maxQueueingTimeoutMs) &&
+ Objects.equals(paramItem, that.paramItem);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, app, ip, port, gmtCreate, gmtModified, resource, resourceMode, grade, count, interval, intervalUnit, controlBehavior, burst, maxQueueingTimeoutMs, paramItem);
+ }
+
+ @Override
+ public String toString() {
+ return "GatewayFlowRuleEntity{" +
+ "id=" + id +
+ ", app='" + app + '\'' +
+ ", ip='" + ip + '\'' +
+ ", port=" + port +
+ ", gmtCreate=" + gmtCreate +
+ ", gmtModified=" + gmtModified +
+ ", resource='" + resource + '\'' +
+ ", resourceMode=" + resourceMode +
+ ", grade=" + grade +
+ ", count=" + count +
+ ", interval=" + interval +
+ ", intervalUnit=" + intervalUnit +
+ ", controlBehavior=" + controlBehavior +
+ ", burst=" + burst +
+ ", maxQueueingTimeoutMs=" + maxQueueingTimeoutMs +
+ ", paramItem=" + paramItem +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayParamFlowItemEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayParamFlowItemEntity.java
new file mode 100755
index 000000000..4da71c8ec
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/gateway/GatewayParamFlowItemEntity.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.gateway;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
+
+import java.util.Objects;
+
+/**
+ * Entity for {@link GatewayParamFlowItem}.
+ *
+ * @author cdfive
+ * @since 1.7.0
+ */
+public class GatewayParamFlowItemEntity {
+
+ private Integer parseStrategy;
+
+ private String fieldName;
+
+ private String pattern;
+
+ private Integer matchStrategy;
+
+ public Integer getParseStrategy() {
+ return parseStrategy;
+ }
+
+ public void setParseStrategy(Integer parseStrategy) {
+ this.parseStrategy = parseStrategy;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public void setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public Integer getMatchStrategy() {
+ return matchStrategy;
+ }
+
+ public void setMatchStrategy(Integer matchStrategy) {
+ this.matchStrategy = matchStrategy;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+ GatewayParamFlowItemEntity that = (GatewayParamFlowItemEntity) o;
+ return Objects.equals(parseStrategy, that.parseStrategy) &&
+ Objects.equals(fieldName, that.fieldName) &&
+ Objects.equals(pattern, that.pattern) &&
+ Objects.equals(matchStrategy, that.matchStrategy);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(parseStrategy, fieldName, pattern, matchStrategy);
+ }
+
+ @Override
+ public String toString() {
+ return "GatewayParamFlowItemEntity{" +
+ "parseStrategy=" + parseStrategy +
+ ", fieldName='" + fieldName + '\'' +
+ ", pattern='" + pattern + '\'' +
+ ", matchStrategy=" + matchStrategy +
+ '}';
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AbstractRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AbstractRuleEntity.java
new file mode 100755
index 000000000..6f60647dc
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AbstractRuleEntity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.slots.block.AbstractRule;
+import com.alibaba.csp.sentinel.slots.block.Rule;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+public abstract class AbstractRuleEntity implements RuleEntity {
+
+ protected Long id;
+
+ protected String app;
+ protected String ip;
+ protected Integer port;
+
+ protected T rule;
+
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public AbstractRuleEntity setApp(String app) {
+ this.app = app;
+ return this;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public AbstractRuleEntity setIp(String ip) {
+ this.ip = ip;
+ return this;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public AbstractRuleEntity setPort(Integer port) {
+ this.port = port;
+ return this;
+ }
+
+ public T getRule() {
+ return rule;
+ }
+
+ public AbstractRuleEntity setRule(T rule) {
+ this.rule = rule;
+ return this;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public AbstractRuleEntity setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ return this;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public AbstractRuleEntity setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ return this;
+ }
+
+ @Override
+ public T toRule() {
+ return rule;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AuthorityRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AuthorityRuleEntity.java
new file mode 100755
index 000000000..924962010
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/AuthorityRuleEntity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+public class AuthorityRuleEntity extends AbstractRuleEntity {
+
+ public AuthorityRuleEntity() {}
+
+ public AuthorityRuleEntity(AuthorityRule authorityRule) {
+ AssertUtil.notNull(authorityRule, "Authority rule should not be null");
+ this.rule = authorityRule;
+ }
+
+ public static AuthorityRuleEntity fromAuthorityRule(String app, String ip, Integer port, AuthorityRule rule) {
+ AuthorityRuleEntity entity = new AuthorityRuleEntity(rule);
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ return entity;
+ }
+
+ @JsonIgnore
+ public String getLimitApp() {
+ return rule.getLimitApp();
+ }
+
+ @JsonIgnore
+ public String getResource() {
+ return rule.getResource();
+ }
+
+ @JsonIgnore
+ public int getStrategy() {
+ return rule.getStrategy();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/DegradeRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/DegradeRuleEntity.java
new file mode 100755
index 000000000..2b86a373a
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/DegradeRuleEntity.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
+
+/**
+ * @author leyou
+ */
+public class DegradeRuleEntity implements RuleEntity {
+ private Long id;
+ private String app;
+ private String ip;
+ private Integer port;
+ private String resource;
+ private String limitApp;
+ private Double count;
+ private Integer timeWindow;
+ /**
+ * 0 rt 限流; 1为异常;
+ */
+ private Integer grade;
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ public static DegradeRuleEntity fromDegradeRule(String app, String ip, Integer port, DegradeRule rule) {
+ DegradeRuleEntity entity = new DegradeRuleEntity();
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ entity.setResource(rule.getResource());
+ entity.setLimitApp(rule.getLimitApp());
+ entity.setCount(rule.getCount());
+ entity.setTimeWindow(rule.getTimeWindow());
+ entity.setGrade(rule.getGrade());
+ return entity;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public String getLimitApp() {
+ return limitApp;
+ }
+
+ public void setLimitApp(String limitApp) {
+ this.limitApp = limitApp;
+ }
+
+ public Double getCount() {
+ return count;
+ }
+
+ public void setCount(Double count) {
+ this.count = count;
+ }
+
+ public Integer getTimeWindow() {
+ return timeWindow;
+ }
+
+ public void setTimeWindow(Integer timeWindow) {
+ this.timeWindow = timeWindow;
+ }
+
+ public Integer getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Integer grade) {
+ this.grade = grade;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ @Override
+ public DegradeRule toRule() {
+ DegradeRule rule = new DegradeRule();
+ rule.setResource(resource);
+ rule.setLimitApp(limitApp);
+ rule.setCount(count);
+ rule.setTimeWindow(timeWindow);
+ rule.setGrade(grade);
+ return rule;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/FlowRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/FlowRuleEntity.java
new file mode 100755
index 000000000..a076bd429
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/FlowRuleEntity.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.slots.block.flow.ClusterFlowConfig;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+
+/**
+ * @author leyou
+ */
+public class FlowRuleEntity implements RuleEntity {
+
+ private Long id;
+ private String app;
+ private String ip;
+ private Integer port;
+ private String limitApp;
+ private String resource;
+ /**
+ * 0为线程数;1为qps
+ */
+ private Integer grade;
+ private Double count;
+ /**
+ * 0为直接限流;1为关联限流;2为链路限流
+ ***/
+ private Integer strategy;
+ private String refResource;
+ /**
+ * 0. default, 1. warm up, 2. rate limiter
+ */
+ private Integer controlBehavior;
+ private Integer warmUpPeriodSec;
+ /**
+ * max queueing time in rate limiter behavior
+ */
+ private Integer maxQueueingTimeMs;
+
+ private boolean clusterMode;
+ /**
+ * Flow rule config for cluster mode.
+ */
+ private ClusterFlowConfig clusterConfig;
+
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ public static FlowRuleEntity fromFlowRule(String app, String ip, Integer port, FlowRule rule) {
+ FlowRuleEntity entity = new FlowRuleEntity();
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ entity.setLimitApp(rule.getLimitApp());
+ entity.setResource(rule.getResource());
+ entity.setGrade(rule.getGrade());
+ entity.setCount(rule.getCount());
+ entity.setStrategy(rule.getStrategy());
+ entity.setRefResource(rule.getRefResource());
+ entity.setControlBehavior(rule.getControlBehavior());
+ entity.setWarmUpPeriodSec(rule.getWarmUpPeriodSec());
+ entity.setMaxQueueingTimeMs(rule.getMaxQueueingTimeMs());
+ entity.setClusterMode(rule.isClusterMode());
+ entity.setClusterConfig(rule.getClusterConfig());
+ return entity;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getLimitApp() {
+ return limitApp;
+ }
+
+ public void setLimitApp(String limitApp) {
+ this.limitApp = limitApp;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public Integer getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Integer grade) {
+ this.grade = grade;
+ }
+
+ public Double getCount() {
+ return count;
+ }
+
+ public void setCount(Double count) {
+ this.count = count;
+ }
+
+ public Integer getStrategy() {
+ return strategy;
+ }
+
+ public void setStrategy(Integer strategy) {
+ this.strategy = strategy;
+ }
+
+ public String getRefResource() {
+ return refResource;
+ }
+
+ public void setRefResource(String refResource) {
+ this.refResource = refResource;
+ }
+
+ public Integer getControlBehavior() {
+ return controlBehavior;
+ }
+
+ public void setControlBehavior(Integer controlBehavior) {
+ this.controlBehavior = controlBehavior;
+ }
+
+ public Integer getWarmUpPeriodSec() {
+ return warmUpPeriodSec;
+ }
+
+ public void setWarmUpPeriodSec(Integer warmUpPeriodSec) {
+ this.warmUpPeriodSec = warmUpPeriodSec;
+ }
+
+ public Integer getMaxQueueingTimeMs() {
+ return maxQueueingTimeMs;
+ }
+
+ public void setMaxQueueingTimeMs(Integer maxQueueingTimeMs) {
+ this.maxQueueingTimeMs = maxQueueingTimeMs;
+ }
+
+ public boolean isClusterMode() {
+ return clusterMode;
+ }
+
+ public FlowRuleEntity setClusterMode(boolean clusterMode) {
+ this.clusterMode = clusterMode;
+ return this;
+ }
+
+ public ClusterFlowConfig getClusterConfig() {
+ return clusterConfig;
+ }
+
+ public FlowRuleEntity setClusterConfig(ClusterFlowConfig clusterConfig) {
+ this.clusterConfig = clusterConfig;
+ return this;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ @Override
+ public FlowRule toRule() {
+ FlowRule flowRule = new FlowRule();
+ flowRule.setCount(this.count);
+ flowRule.setGrade(this.grade);
+ flowRule.setResource(this.resource);
+ flowRule.setLimitApp(this.limitApp);
+ flowRule.setRefResource(this.refResource);
+ flowRule.setStrategy(this.strategy);
+ if (this.controlBehavior != null) {
+ flowRule.setControlBehavior(controlBehavior);
+ }
+ if (this.warmUpPeriodSec != null) {
+ flowRule.setWarmUpPeriodSec(warmUpPeriodSec);
+ }
+ if (this.maxQueueingTimeMs != null) {
+ flowRule.setMaxQueueingTimeMs(maxQueueingTimeMs);
+ }
+ flowRule.setClusterMode(clusterMode);
+ flowRule.setClusterConfig(clusterConfig);
+ return flowRule;
+ }
+
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java
new file mode 100755
index 000000000..5ffb1fe10
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import java.util.List;
+
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowClusterConfig;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
+import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * @author Eric Zhao
+ * @since 0.2.1
+ */
+public class ParamFlowRuleEntity extends AbstractRuleEntity {
+
+ public ParamFlowRuleEntity() {}
+
+ public ParamFlowRuleEntity(ParamFlowRule rule) {
+ AssertUtil.notNull(rule, "Authority rule should not be null");
+ this.rule = rule;
+ }
+
+ public static ParamFlowRuleEntity fromAuthorityRule(String app, String ip, Integer port, ParamFlowRule rule) {
+ ParamFlowRuleEntity entity = new ParamFlowRuleEntity(rule);
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ return entity;
+ }
+
+ @JsonIgnore
+ public String getLimitApp() {
+ return rule.getLimitApp();
+ }
+
+ @JsonIgnore
+ public String getResource() {
+ return rule.getResource();
+ }
+
+ @JsonIgnore
+ public int getGrade() {
+ return rule.getGrade();
+ }
+
+ @JsonIgnore
+ public Integer getParamIdx() {
+ return rule.getParamIdx();
+ }
+
+ @JsonIgnore
+ public double getCount() {
+ return rule.getCount();
+ }
+
+ @JsonIgnore
+ public List getParamFlowItemList() {
+ return rule.getParamFlowItemList();
+ }
+
+ @JsonIgnore
+ public int getControlBehavior() {
+ return rule.getControlBehavior();
+ }
+
+ @JsonIgnore
+ public int getMaxQueueingTimeMs() {
+ return rule.getMaxQueueingTimeMs();
+ }
+
+ @JsonIgnore
+ public int getBurstCount() {
+ return rule.getBurstCount();
+ }
+
+ @JsonIgnore
+ public long getDurationInSec() {
+ return rule.getDurationInSec();
+ }
+
+ @JsonIgnore
+ public boolean isClusterMode() {
+ return rule.isClusterMode();
+ }
+
+ @JsonIgnore
+ public ParamFlowClusterConfig getClusterConfig() {
+ return rule.getClusterConfig();
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/RuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/RuleEntity.java
new file mode 100755
index 000000000..0ad764fe3
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/RuleEntity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import java.util.Date;
+
+import com.alibaba.csp.sentinel.slots.block.Rule;
+
+/**
+ * @author leyou
+ */
+public interface RuleEntity {
+
+ Long getId();
+
+ void setId(Long id);
+
+ String getApp();
+
+ String getIp();
+
+ Integer getPort();
+
+ Date getGmtCreate();
+
+ Rule toRule();
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java
new file mode 100755
index 000000000..483ebcb52
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/rule/SystemRuleEntity.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.datasource.entity.rule;
+
+import com.alibaba.csp.sentinel.slots.system.SystemRule;
+
+import java.util.Date;
+
+/**
+ * @author leyou
+ */
+public class SystemRuleEntity implements RuleEntity {
+
+ private Long id;
+
+ private String app;
+ private String ip;
+ private Integer port;
+ private Double highestSystemLoad;
+ private Long avgRt;
+ private Long maxThread;
+ private Double qps;
+ private Double highestCpuUsage;
+
+ private Date gmtCreate;
+ private Date gmtModified;
+
+ public static SystemRuleEntity fromSystemRule(String app, String ip, Integer port, SystemRule rule) {
+ SystemRuleEntity entity = new SystemRuleEntity();
+ entity.setApp(app);
+ entity.setIp(ip);
+ entity.setPort(port);
+ entity.setHighestSystemLoad(rule.getHighestSystemLoad());
+ entity.setHighestCpuUsage(rule.getHighestCpuUsage());
+ entity.setAvgRt(rule.getAvgRt());
+ entity.setMaxThread(rule.getMaxThread());
+ entity.setQps(rule.getQps());
+ return entity;
+ }
+
+ @Override
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ @Override
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public Double getHighestSystemLoad() {
+ return highestSystemLoad;
+ }
+
+ public void setHighestSystemLoad(Double highestSystemLoad) {
+ this.highestSystemLoad = highestSystemLoad;
+ }
+
+ public Long getAvgRt() {
+ return avgRt;
+ }
+
+ public void setAvgRt(Long avgRt) {
+ this.avgRt = avgRt;
+ }
+
+ public Long getMaxThread() {
+ return maxThread;
+ }
+
+ public void setMaxThread(Long maxThread) {
+ this.maxThread = maxThread;
+ }
+
+ public Double getQps() {
+ return qps;
+ }
+
+ public void setQps(Double qps) {
+ this.qps = qps;
+ }
+
+ public Double getHighestCpuUsage() {
+ return highestCpuUsage;
+ }
+
+ public void setHighestCpuUsage(Double highestCpuUsage) {
+ this.highestCpuUsage = highestCpuUsage;
+ }
+
+ @Override
+ public Date getGmtCreate() {
+ return gmtCreate;
+ }
+
+ public void setGmtCreate(Date gmtCreate) {
+ this.gmtCreate = gmtCreate;
+ }
+
+ public Date getGmtModified() {
+ return gmtModified;
+ }
+
+ public void setGmtModified(Date gmtModified) {
+ this.gmtModified = gmtModified;
+ }
+
+ @Override
+ public SystemRule toRule() {
+ SystemRule rule = new SystemRule();
+ rule.setHighestSystemLoad(highestSystemLoad);
+ rule.setAvgRt(avgRt);
+ rule.setMaxThread(maxThread);
+ rule.setQps(qps);
+ rule.setHighestCpuUsage(highestCpuUsage);
+ return rule;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java
new file mode 100755
index 000000000..f7697698c
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppInfo.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.discovery;
+
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig;
+
+public class AppInfo {
+
+ private String app = "";
+
+ private Integer appType = 0;
+
+ private Set machines = ConcurrentHashMap.newKeySet();
+
+ public AppInfo() {}
+
+ public AppInfo(String app) {
+ this.app = app;
+ }
+
+ public AppInfo(String app, Integer appType) {
+ this.app = app;
+ this.appType = appType;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public Integer getAppType() {
+ return appType;
+ }
+
+ public void setAppType(Integer appType) {
+ this.appType = appType;
+ }
+
+ /**
+ * Get the current machines.
+ *
+ * @return a new copy of the current machines.
+ */
+ public Set getMachines() {
+ return new HashSet<>(machines);
+ }
+
+ @Override
+ public String toString() {
+ return "AppInfo{" + "app='" + app + ", machines=" + machines + '}';
+ }
+
+ public boolean addMachine(MachineInfo machineInfo) {
+ machines.remove(machineInfo);
+ return machines.add(machineInfo);
+ }
+
+ public synchronized boolean removeMachine(String ip, int port) {
+ Iterator it = machines.iterator();
+ while (it.hasNext()) {
+ MachineInfo machine = it.next();
+ if (machine.getIp().equals(ip) && machine.getPort() == port) {
+ it.remove();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Optional getMachine(String ip, int port) {
+ return machines.stream()
+ .filter(e -> e.getIp().equals(ip) && e.getPort().equals(port))
+ .findFirst();
+ }
+
+ private boolean heartbeatJudge(final int threshold) {
+ if (machines.size() == 0) {
+ return false;
+ }
+ if (threshold > 0) {
+ long healthyCount = machines.stream()
+ .filter(MachineInfo::isHealthy)
+ .count();
+ if (healthyCount == 0) {
+ // No healthy machines.
+ return machines.stream()
+ .max(Comparator.comparingLong(MachineInfo::getLastHeartbeat))
+ .map(e -> System.currentTimeMillis() - e.getLastHeartbeat() < threshold)
+ .orElse(false);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check whether current application has no healthy machines and should not be displayed.
+ *
+ * @return true if the application should be displayed in the sidebar, otherwise false
+ */
+ public boolean isShown() {
+ return heartbeatJudge(DashboardConfig.getHideAppNoMachineMillis());
+ }
+
+ /**
+ * Check whether current application has no healthy machines and should be removed.
+ *
+ * @return true if the application is dead and should be removed, otherwise false
+ */
+ public boolean isDead() {
+ return !heartbeatJudge(DashboardConfig.getRemoveAppNoMachineMillis());
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java
new file mode 100755
index 000000000..9e44336f1
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/AppManagement.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.discovery;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AppManagement implements MachineDiscovery {
+
+ @Autowired
+ private ApplicationContext context;
+
+ private MachineDiscovery machineDiscovery;
+
+ @PostConstruct
+ public void init() {
+ machineDiscovery = context.getBean(SimpleMachineDiscovery.class);
+ }
+
+ @Override
+ public Set getBriefApps() {
+ return machineDiscovery.getBriefApps();
+ }
+
+ @Override
+ public long addMachine(MachineInfo machineInfo) {
+ return machineDiscovery.addMachine(machineInfo);
+ }
+
+ @Override
+ public boolean removeMachine(String app, String ip, int port) {
+ return machineDiscovery.removeMachine(app, ip, port);
+ }
+
+ @Override
+ public List getAppNames() {
+ return machineDiscovery.getAppNames();
+ }
+
+ @Override
+ public AppInfo getDetailApp(String app) {
+ return machineDiscovery.getDetailApp(app);
+ }
+
+ @Override
+ public void removeApp(String app) {
+ machineDiscovery.removeApp(app);
+ }
+
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java
new file mode 100755
index 000000000..260b0d8c3
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineDiscovery.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.discovery;
+
+import java.util.List;
+import java.util.Set;
+
+public interface MachineDiscovery {
+
+ String UNKNOWN_APP_NAME = "CLUSTER_NOT_STARTED";
+
+ List getAppNames();
+
+ Set getBriefApps();
+
+ AppInfo getDetailApp(String app);
+
+ /**
+ * Remove the given app from the application registry.
+ *
+ * @param app application name
+ * @since 1.5.0
+ */
+ void removeApp(String app);
+
+ long addMachine(MachineInfo machineInfo);
+
+ /**
+ * Remove the given machine instance from the application registry.
+ *
+ * @param app the application name of the machine
+ * @param ip machine IP
+ * @param port machine port
+ * @return true if removed, otherwise false
+ * @since 1.5.0
+ */
+ boolean removeMachine(String app, String ip, int port);
+}
\ No newline at end of file
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java
new file mode 100755
index 000000000..afcc81243
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/MachineInfo.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.discovery;
+
+import java.util.Objects;
+
+import com.alibaba.csp.sentinel.dashboard.config.DashboardConfig;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+public class MachineInfo implements Comparable {
+
+ private String app = "";
+ private Integer appType = 0;
+ private String hostname = "";
+ private String ip = "";
+ private Integer port = -1;
+ private long lastHeartbeat;
+ private long heartbeatVersion;
+
+ /**
+ * Indicates the version of Sentinel client (since 0.2.0).
+ */
+ private String version;
+
+ public static MachineInfo of(String app, String ip, Integer port) {
+ MachineInfo machineInfo = new MachineInfo();
+ machineInfo.setApp(app);
+ machineInfo.setIp(ip);
+ machineInfo.setPort(port);
+ return machineInfo;
+ }
+
+ public String toHostPort() {
+ return ip + ":" + port;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public void setApp(String app) {
+ this.app = app;
+ }
+
+ public Integer getAppType() {
+ return appType;
+ }
+
+ public void setAppType(Integer appType) {
+ this.appType = appType;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public long getHeartbeatVersion() {
+ return heartbeatVersion;
+ }
+
+ public void setHeartbeatVersion(long heartbeatVersion) {
+ this.heartbeatVersion = heartbeatVersion;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public MachineInfo setVersion(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public boolean isHealthy() {
+ long delta = System.currentTimeMillis() - lastHeartbeat;
+ return delta < DashboardConfig.getUnhealthyMachineMillis();
+ }
+
+ /**
+ * whether dead should be removed
+ *
+ * @return
+ */
+ public boolean isDead() {
+ if (DashboardConfig.getAutoRemoveMachineMillis() > 0) {
+ long delta = System.currentTimeMillis() - lastHeartbeat;
+ return delta > DashboardConfig.getAutoRemoveMachineMillis();
+ }
+ return false;
+ }
+
+ public long getLastHeartbeat() {
+ return lastHeartbeat;
+ }
+
+ public void setLastHeartbeat(long lastHeartbeat) {
+ this.lastHeartbeat = lastHeartbeat;
+ }
+
+ @Override
+ public int compareTo(MachineInfo o) {
+ if (this == o) {
+ return 0;
+ }
+ if (!port.equals(o.getPort())) {
+ return port.compareTo(o.getPort());
+ }
+ if (!StringUtil.equals(app, o.getApp())) {
+ return app.compareToIgnoreCase(o.getApp());
+ }
+ return ip.compareToIgnoreCase(o.getIp());
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder("MachineInfo {")
+ .append("app='").append(app).append('\'')
+ .append(",appType='").append(appType).append('\'')
+ .append(", hostname='").append(hostname).append('\'')
+ .append(", ip='").append(ip).append('\'')
+ .append(", port=").append(port)
+ .append(", heartbeatVersion=").append(heartbeatVersion)
+ .append(", lastHeartbeat=").append(lastHeartbeat)
+ .append(", version='").append(version).append('\'')
+ .append(", healthy=").append(isHealthy())
+ .append('}').toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (!(o instanceof MachineInfo)) { return false; }
+ MachineInfo that = (MachineInfo)o;
+ return Objects.equals(app, that.app) &&
+ Objects.equals(ip, that.ip) &&
+ Objects.equals(port, that.port);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(app, ip, port);
+ }
+
+ /**
+ * Information for log
+ *
+ * @return
+ */
+ public String toLogString() {
+ return app + "|" + ip + "|" + port + "|" + version;
+ }
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java
new file mode 100755
index 000000000..a4ab83acd
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/discovery/SimpleMachineDiscovery.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.discovery;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.alibaba.csp.sentinel.util.AssertUtil;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @author leyou
+ */
+@Component
+public class SimpleMachineDiscovery implements MachineDiscovery {
+
+ private final ConcurrentMap apps = new ConcurrentHashMap<>();
+
+ @Override
+ public long addMachine(MachineInfo machineInfo) {
+ AssertUtil.notNull(machineInfo, "machineInfo cannot be null");
+ AppInfo appInfo = apps.computeIfAbsent(machineInfo.getApp(), o -> new AppInfo(machineInfo.getApp(), machineInfo.getAppType()));
+ appInfo.addMachine(machineInfo);
+ return 1;
+ }
+
+ @Override
+ public boolean removeMachine(String app, String ip, int port) {
+ AssertUtil.assertNotBlank(app, "app name cannot be blank");
+ AppInfo appInfo = apps.get(app);
+ if (appInfo != null) {
+ return appInfo.removeMachine(ip, port);
+ }
+ return false;
+ }
+
+ @Override
+ public List getAppNames() {
+ return new ArrayList<>(apps.keySet());
+ }
+
+ @Override
+ public AppInfo getDetailApp(String app) {
+ AssertUtil.assertNotBlank(app, "app name cannot be blank");
+ return apps.get(app);
+ }
+
+ @Override
+ public Set getBriefApps() {
+ return new HashSet<>(apps.values());
+ }
+
+ @Override
+ public void removeApp(String app) {
+ AssertUtil.assertNotBlank(app, "app name cannot be blank");
+ apps.remove(app);
+ }
+
+}
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/ResourceTreeNode.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/ResourceTreeNode.java
new file mode 100755
index 000000000..fa2e7ca9b
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/ResourceTreeNode.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.domain;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.csp.sentinel.command.vo.NodeVo;
+
+/**
+ * @author leyou
+ */
+public class ResourceTreeNode {
+ private String id;
+ private String parentId;
+ private String resource;
+
+ private Integer threadNum;
+ private Long passQps;
+ private Long blockQps;
+ private Long totalQps;
+ private Long averageRt;
+ private Long successQps;
+ private Long exceptionQps;
+ private Long oneMinutePass;
+ private Long oneMinuteBlock;
+ private Long oneMinuteException;
+ private Long oneMinuteTotal;
+
+ private boolean visible = true;
+
+ private List children = new ArrayList<>();
+
+ public static ResourceTreeNode fromNodeVoList(List nodeVos) {
+ if (nodeVos == null || nodeVos.isEmpty()) {
+ return null;
+ }
+ ResourceTreeNode root = null;
+ Map map = new HashMap<>();
+ for (NodeVo vo : nodeVos) {
+ ResourceTreeNode node = fromNodeVo(vo);
+ map.put(node.id, node);
+ // real root
+ if (node.parentId == null) {
+ root = node;
+ } else if (map.containsKey(node.parentId)) {
+ map.get(node.parentId).children.add(node);
+ } else {
+ // impossible
+ }
+ }
+ return root;
+ }
+
+ public static ResourceTreeNode fromNodeVo(NodeVo vo) {
+ ResourceTreeNode node = new ResourceTreeNode();
+ node.id = vo.getId();
+ node.parentId = vo.getParentId();
+ node.resource = vo.getResource();
+ node.threadNum = vo.getThreadNum();
+ node.passQps = vo.getPassQps();
+ node.blockQps = vo.getBlockQps();
+ node.totalQps = vo.getTotalQps();
+ node.averageRt = vo.getAverageRt();
+ node.successQps = vo.getSuccessQps();
+ node.exceptionQps = vo.getExceptionQps();
+ node.oneMinutePass = vo.getOneMinutePass();
+ node.oneMinuteBlock = vo.getOneMinuteBlock();
+ node.oneMinuteException = vo.getOneMinuteException();
+ node.oneMinuteTotal = vo.getOneMinuteTotal();
+ return node;
+ }
+
+ public void searchIgnoreCase(String searchKey) {
+ search(this, searchKey);
+ }
+
+ /**
+ * This node is visible only when searchKey matches this.resource or at least
+ * one of this's children is visible
+ */
+ private boolean search(ResourceTreeNode node, String searchKey) {
+ // empty matches all
+ if (searchKey == null || searchKey.isEmpty() ||
+ node.resource.toLowerCase().contains(searchKey.toLowerCase())) {
+ node.visible = true;
+ } else {
+ node.visible = false;
+ }
+
+ boolean found = false;
+ for (ResourceTreeNode c : node.children) {
+ found |= search(c, searchKey);
+ }
+ node.visible |= found;
+ return node.visible;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(String parentId) {
+ this.parentId = parentId;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public Integer getThreadNum() {
+ return threadNum;
+ }
+
+ public void setThreadNum(Integer threadNum) {
+ this.threadNum = threadNum;
+ }
+
+ public Long getPassQps() {
+ return passQps;
+ }
+
+ public void setPassQps(Long passQps) {
+ this.passQps = passQps;
+ }
+
+ public Long getBlockQps() {
+ return blockQps;
+ }
+
+ public void setBlockQps(Long blockQps) {
+ this.blockQps = blockQps;
+ }
+
+ public Long getTotalQps() {
+ return totalQps;
+ }
+
+ public void setTotalQps(Long totalQps) {
+ this.totalQps = totalQps;
+ }
+
+ public Long getAverageRt() {
+ return averageRt;
+ }
+
+ public void setAverageRt(Long averageRt) {
+ this.averageRt = averageRt;
+ }
+
+ public Long getSuccessQps() {
+ return successQps;
+ }
+
+ public void setSuccessQps(Long successQps) {
+ this.successQps = successQps;
+ }
+
+ public Long getExceptionQps() {
+ return exceptionQps;
+ }
+
+ public void setExceptionQps(Long exceptionQps) {
+ this.exceptionQps = exceptionQps;
+ }
+
+ public Long getOneMinutePass() {
+ return oneMinutePass;
+ }
+
+ public void setOneMinutePass(Long oneMinutePass) {
+ this.oneMinutePass = oneMinutePass;
+ }
+
+ public Long getOneMinuteBlock() {
+ return oneMinuteBlock;
+ }
+
+ public void setOneMinuteBlock(Long oneMinuteBlock) {
+ this.oneMinuteBlock = oneMinuteBlock;
+ }
+
+ public Long getOneMinuteException() {
+ return oneMinuteException;
+ }
+
+ public void setOneMinuteException(Long oneMinuteException) {
+ this.oneMinuteException = oneMinuteException;
+ }
+
+ public Long getOneMinuteTotal() {
+ return oneMinuteTotal;
+ }
+
+ public void setOneMinuteTotal(Long oneMinuteTotal) {
+ this.oneMinuteTotal = oneMinuteTotal;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ public List getChildren() {
+ return children;
+ }
+
+ public void setChildren(List children) {
+ this.children = children;
+ }
+}
+
diff --git a/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/Result.java b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/Result.java
new file mode 100755
index 000000000..2dbf476f0
--- /dev/null
+++ b/pigx-visual/pigx-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/domain/Result.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1999-2018 Alibaba Group Holding Ltd.
+ *
+ * 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.alibaba.csp.sentinel.dashboard.domain;
+
+/**
+ * @author leyou
+ * @author Eric Zhao
+ */
+public class Result {
+
+ private boolean success;
+ private int code;
+ private String msg;
+ private R data;
+
+ public static Result ofSuccess(R data) {
+ return new Result()
+ .setSuccess(true)
+ .setMsg("success")
+ .setData(data);
+ }
+
+ public static Result ofSuccessMsg(String msg) {
+ return new Result()
+ .setSuccess(true)
+ .setMsg(msg);
+ }
+
+ public static Result ofFail(int code, String msg) {
+ Result result = new Result<>();
+ result.setSuccess(false);
+ result.setCode(code);
+ result.setMsg(msg);
+ return result;
+ }
+
+ public static Result ofThrowable(int code, Throwable throwable) {
+ Result result = new Result<>();
+ result.setSuccess(false);
+ result.setCode(code);
+ result.setMsg(throwable.getClass().getName() + ", " + throwable.getMessage());
+ return result;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public Result setSuccess(boolean success) {
+ this.success = success;
+ return this;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public Result setCode(int code) {
+ this.code = code;
+ return this;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public Result setMsg(String msg) {
+ this.msg = msg;
+ return this;
+ }
+
+ public R getData() {
+ return data;
+ }
+
+ public Result