Browse Source

支持绝对路径的模糊匹配

rain 1 year ago
parent
commit
70954b4ae2
18 changed files with 170 additions and 53 deletions
  1. 5 3
      liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java
  2. 73 0
      liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java
  3. 45 38
      liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java
  4. 5 2
      liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java
  5. 2 1
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties
  6. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  7. 2 1
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties
  8. 1 1
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  9. 1 0
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java
  10. 7 1
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml
  11. 2 1
      liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties
  12. 1 1
      liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml
  13. 16 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java
  14. 2 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties
  15. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml
  16. 1 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties
  17. 4 0
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml
  18. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml

+ 5 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java

@@ -9,6 +9,7 @@ import cn.hutool.core.util.ClassLoaderUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.exception.ConfigErrorException;
 import com.yomahub.liteflow.spi.PathContentParser;
+import com.yomahub.liteflow.util.PathMatchUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -24,10 +25,11 @@ public class LocalPathContentParser implements PathContentParser {
 		if (CollectionUtil.isEmpty(pathList)) {
 			throw new ConfigErrorException("rule source must not be null");
 		}
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
 
 		List<String> contentList = new ArrayList<>();
 
-		for (String path : pathList) {
+		for (String path : absolutePathList) {
 			if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) {
 				path = FILE_URL_PREFIX + path;
 			}
@@ -50,10 +52,10 @@ public class LocalPathContentParser implements PathContentParser {
 		if (CollectionUtil.isEmpty(pathList)) {
 			throw new ConfigErrorException("rule source must not be null");
 		}
-
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
 		List<String> result = new ArrayList<>();
 
-		for (String path : pathList) {
+		for (String path : absolutePathList) {
 			if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) {
 				path = FILE_URL_PREFIX + path;
 				result.add(new FileResource(path).getFile().getAbsolutePath());

+ 73 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java

@@ -0,0 +1,73 @@
+package com.yomahub.liteflow.util;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.text.AntPathMatcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 用于获取模糊匹配的路径
+ *
+ * @author Rain
+ * @since 2.11.1
+ */
+public class PathMatchUtil {
+
+    public static List<String> searchAbsolutePath(List<String> pathList) {
+
+        List<String> absolutePathList = new ArrayList<>();
+
+        for (String path : pathList) {
+            // 只对绝对路径进行处理
+            if(FileUtil.isAbsolutePath(path)) {
+                if(!path.contains("*")) {
+                    absolutePathList.add(path);
+                }
+                else {
+                    String[] pathSegments = path.split("/");
+                    StringBuilder baseDir = new StringBuilder();
+
+                    // 找到最大基础路径
+                    for(int i = 0; i < pathSegments.length; i ++) {
+                        if(!pathSegments[i].contains("*")) {
+                            baseDir.append(pathSegments[i]).append(File.separator);
+                        } else {
+                            baseDir.deleteCharAt(baseDir.length() - 1);
+                            searchAbsolutePath(baseDir.toString(), path, absolutePathList);
+                            break;
+                        }
+                    }
+                }
+            } else {
+                absolutePathList.add(path);
+            }
+        }
+        // 路径去重
+        List<String> newAbsolutePathList = absolutePathList.stream()
+                .distinct()
+                .collect(Collectors.toList());
+        return newAbsolutePathList;
+    }
+
+    private static void searchAbsolutePath(String baseDir, String path, List<String> absolutePathList) {
+        AntPathMatcher pathMatcher = new AntPathMatcher();
+        File dir = new File(baseDir);
+        File[] files = dir.listFiles();
+
+        if (files != null) {
+            for (File file : files) {
+                if (file.isDirectory()) {
+                    searchAbsolutePath(file.getAbsolutePath(), path, absolutePathList);
+                } else {
+                    String absolutePath = file.getAbsolutePath().replace("\\", "/");
+                    if (pathMatcher.match(path, absolutePath)) {
+                        absolutePathList.add(absolutePath);
+                    }
+                }
+            }
+        }
+    }
+}

+ 45 - 38
liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java

@@ -1,8 +1,11 @@
 package com.yomahub.liteflow.solon.config;
 
+import cn.hutool.core.io.FileUtil;
+import com.yomahub.liteflow.util.PathMatchUtil;
 import org.noear.solon.core.util.ScanUtil;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -17,51 +20,55 @@ public class PathsUtils {
 
 	public static Collection<String> resolvePaths(String pathExpr) {
 		List<String> paths = new ArrayList<>();
+		if(!FileUtil.isAbsolutePath(pathExpr)) {
+			if (pathExpr.contains("/*") == false) { // 说明没有*符
+				paths.add(pathExpr);
+				return paths;
+			}
 
-		if (pathExpr.contains("/*") == false) { // 说明没有*符
-			paths.add(pathExpr);
-			return paths;
-		}
-
-		// 确定目录
-		int dirIdx = pathExpr.indexOf("/*");
-		String dir = pathExpr.substring(0, dirIdx);
+			// 确定目录
+			int dirIdx = pathExpr.indexOf("/*");
+			String dir = pathExpr.substring(0, dirIdx);
 
-		// 确定后缀
-		int sufIdx = pathExpr.lastIndexOf(".");
-		String suf = null;
-		if (sufIdx > 0) {
-			suf = pathExpr.substring(sufIdx);
-			if (suf.contains("*")) {
-				sufIdx = -1;
-				suf = null;
+			// 确定后缀
+			int sufIdx = pathExpr.lastIndexOf(".");
+			String suf = null;
+			if (sufIdx > 0) {
+				suf = pathExpr.substring(sufIdx);
+				if (suf.contains("*")) {
+					sufIdx = -1;
+					suf = null;
+				}
 			}
-		}
 
-		int sufIdx2 = sufIdx;
-		String suf2 = suf;
+			int sufIdx2 = sufIdx;
+			String suf2 = suf;
 
-		// 匹配表达式
-		String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\.");
-		expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/");
+			// 匹配表达式
+			String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\.");
+			expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/");
 
-		Pattern pattern = Pattern.compile(expr);
-
-		ScanUtil.scan(dir, n -> {
-			// 进行后缀过滤,相对比较快
-			if (sufIdx2 > 0) {
-				return n.endsWith(suf2);
-			}
-			else {
-				return true;
-			}
-		}).forEach(uri -> {
-			// 再进行表达式过滤
-			if (pattern.matcher(uri).find()) {
-				paths.add(uri);
-			}
-		});
+			Pattern pattern = Pattern.compile(expr);
 
+			List<String> finalPaths = paths;
+			ScanUtil.scan(dir, n -> {
+				// 进行后缀过滤,相对比较快
+				if (sufIdx2 > 0) {
+					return n.endsWith(suf2);
+				}
+				else {
+					return true;
+				}
+			}).forEach(uri -> {
+				// 再进行表达式过滤
+				if (pattern.matcher(uri).find()) {
+					finalPaths.add(uri);
+				}
+			});
+		} else {
+			String[] pathExprs = pathExpr.split(",");
+			paths = PathMatchUtil.searchAbsolutePath(Arrays.asList(pathExprs));
+		}
 		return paths;
 	}
 

+ 5 - 2
liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java

@@ -10,6 +10,7 @@ import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.exception.ConfigErrorException;
 import com.yomahub.liteflow.spi.PathContentParser;
+import com.yomahub.liteflow.util.PathMatchUtil;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 import org.springframework.core.io.support.ResourcePatternResolver;
@@ -26,7 +27,8 @@ public class SpringPathContentParser implements PathContentParser {
 
 	@Override
 	public List<String> parseContent(List<String> pathList) throws Exception {
-		List<Resource> allResource = getResources(pathList);
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
+		List<Resource> allResource = getResources(absolutePathList);
 
 		// 转换成内容List
 		List<String> contentList = new ArrayList<>();
@@ -42,7 +44,8 @@ public class SpringPathContentParser implements PathContentParser {
 
 	@Override
 	public List<String> getFileAbsolutePath(List<String> pathList) throws Exception {
-		List<Resource> allResource = getResources(pathList);
+		List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
+		List<Resource> allResource = getResources(absolutePathList);
 
 		return StreamUtil.of(allResource)
 			// 过滤非 file 类型 Resource

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1,2 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=/usr/local/flow.el.xml
+#liteflow.rule-source=/usr/**/*.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1,2 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=/usr/local/flow.el.xml
+#liteflow.rule-source=/usr/**/*.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java

@@ -23,6 +23,7 @@ public class AbsoluteConfigPathTest extends BaseTest {
 	public static void init() {
 		LiteflowConfig config = new LiteflowConfig();
 		config.setRuleSource("/usr/local/flow2.xml");
+//		config.setRuleSource("/usr/**/*.xml");
 		flowExecutor = FlowExecutorHolder.loadInstance(config);
 	}
 

+ 7 - 1
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,6 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
+    <nodes>
+        <node id="a" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.ACmp"/>
+        <node id="b" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.BCmp"/>
+        <node id="c" class="com.yomahub.liteflow.test.absoluteConfigPath.cmp.CCmp"/>
+    </nodes>
+
     <chain name="chain1">
         WHEN(a,b,c);
     </chain>

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1,2 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=/usr/local/flow.el.xml
+#liteflow.rule-source=/usr/**/*.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 16 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java

@@ -38,6 +38,22 @@ public class MonitorFileELSpringbootTest extends BaseTest {
 		Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr());
 	}
 
+    /**
+     * 对绝对路径模糊匹配功能的测试
+     */
+    @Test
+    public void testMonitorAbsolutePath() throws Exception {
+        String absolutePath = "/your/path/dir";
+        FileUtil.writeString("<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">THEN(a, b, c);</chain></flow>", new File(absolutePath), CharsetUtil.CHARSET_UTF_8);
+        String content = FileUtil.readUtf8String(absolutePath);
+        String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);");
+        Thread.sleep(1000);
+        FileUtil.writeString(newContent, new File(absolutePath), CharsetUtil.CHARSET_UTF_8);
+        Thread.sleep(3000);
+        LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+        Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr());
+    }
+
     /**
      * 测试文件变更,但是 EL 规则错误情况
      * 输出 ERROR 日志异常信息,但是不会停止监听线程,当下一次变更正确后替换为新规则

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties

@@ -1 +1,2 @@
-liteflow.rule-source=/usr/local/flow.el.xml
+liteflow.rule-source=/usr/local/flow.el.xml
+#liteflow.rule-source=/usr/**/*.xml

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties

@@ -1,2 +1,3 @@
 liteflow.rule-source=monitorFile/flow.el.xml
+#liteflow.rule-source=/usr/**/*.xml
 liteflow.enable-monitor-file=true

+ 4 - 0
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml

@@ -17,6 +17,10 @@
         <property name="ruleSource" value="/usr/local/flow.el.xml"/>
     </bean>
 
+<!--    <bean id="liteflowConfig" class="com.yomahub.liteflow.property.LiteflowConfig">-->
+<!--        <property name="ruleSource" value="/usr/**/*.xml"/>-->
+<!--    </bean>-->
+
     <bean id="flowExecutor" class="com.yomahub.liteflow.core.FlowExecutor">
         <constructor-arg name="liteflowConfig" ref="liteflowConfig"/>
     </bean>

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.el.xml中-->
+<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.el.xml中,文件目录支持绝对路径的模糊匹配,也可以将此文件移入任意/usr/**/*.xml中-->
 <flow>
     <chain name="chain1">
         WHEN(a,b,c);