Browse files

bugfix: ClassNameWildcard/PathNameWildcard,当以?开头或结尾时,不能正确匹配的问题。

  • Loading branch information...
1 parent b30c736 commit f696d311fd2dd381a69ee791732f18a829be79e8 Michael Zhou committed Aug 18, 2012
View
31 common/util/src/main/java/com/alibaba/citrus/util/regex/ClassNameWildcardCompiler.java
@@ -61,6 +61,7 @@
private static final String REGEX_CLASS_NAME = "(" + REGEX_CLASS_NAME_CHAR + "*)";
private static final String REGEX_CLASS_NAME_FULL = "(" + REGEX_CLASS_NAME_CHAR + "+(?:" + REGEX_DOT_NO_DUP
+ REGEX_CLASS_NAME_CHAR + "*)*(?=" + REGEX_DOT + "|$)|)" + REGEX_DOT + "?";
+ private static final String REGEX_END_OF_NAME = "(?=" + REGEX_DOT + "|$)";
// 上一个token的状态
private static final int LAST_TOKEN_START = 0;
@@ -119,12 +120,12 @@ public static String classNameToRegex(String pattern, int options) throws Patter
pattern = assertNotNull(normalizeClassName(pattern), "pattern");
int lastToken = LAST_TOKEN_START;
- StringBuilder buffer = new StringBuilder(pattern.length() * 2);
+ StringBuilder buf = new StringBuilder(pattern.length() * 2);
boolean matchPrefix = (options & MATCH_PREFIX) != 0;
if (matchPrefix) {
- buffer.append(REGEX_MATCH_PREFIX);
+ buf.append(REGEX_MATCH_PREFIX);
}
for (int i = 0; i < pattern.length(); i++) {
@@ -139,7 +140,7 @@ public static String classNameToRegex(String pattern, int options) throws Patter
// 因为**已经包括了dot, 所以不需要额外地匹配dot
if (lastToken != LAST_TOKEN_DOUBLE_STAR) {
- buffer.append(REGEX_DOT_NO_DUP);
+ buf.append(REGEX_DOT_NO_DUP);
}
lastToken = LAST_TOKEN_DOT;
@@ -157,22 +158,30 @@ public static String classNameToRegex(String pattern, int options) throws Patter
}
lastToken = LAST_TOKEN_DOUBLE_STAR;
- buffer.append(REGEX_CLASS_NAME_FULL);
+ buf.append(REGEX_CLASS_NAME_FULL);
} else {
// *前面不能是*或**
if (lastToken == LAST_TOKEN_STAR || lastToken == LAST_TOKEN_DOUBLE_STAR) {
throw new PatternSyntaxException("Syntax Error", pattern, i);
}
lastToken = LAST_TOKEN_STAR;
- buffer.append(REGEX_CLASS_NAME);
+ buf.append(REGEX_CLASS_NAME);
}
break;
case QUESTION:
+ if (lastToken == LAST_TOKEN_START) {
+ buf.append(REGEX_WORD_BOUNDARY).append(REGEX_CLASS_NAME_SINGLE_CHAR); // 前边界
+ } else if (i + 1 == pattern.length()) {
+ buf.append(REGEX_CLASS_NAME_SINGLE_CHAR).append(REGEX_END_OF_NAME); // 后边界
+ } else {
+ buf.append(REGEX_CLASS_NAME_SINGLE_CHAR);
+ }
+
lastToken = LAST_TOKEN_QUESTION;
- buffer.append(REGEX_CLASS_NAME_SINGLE_CHAR);
+
break;
default:
@@ -184,14 +193,14 @@ public static String classNameToRegex(String pattern, int options) throws Patter
if (Character.isLetterOrDigit(ch) || ch == UNDERSCORE) {
// 加上word边界, 进行整字匹配
if (lastToken == LAST_TOKEN_START) {
- buffer.append(REGEX_WORD_BOUNDARY).append(ch); // 前边界
+ buf.append(REGEX_WORD_BOUNDARY).append(ch); // 前边界
} else if (i + 1 == pattern.length()) {
- buffer.append(ch).append(REGEX_WORD_BOUNDARY); // 后边界
+ buf.append(ch).append(REGEX_WORD_BOUNDARY); // 后边界
} else {
- buffer.append(ch);
+ buf.append(ch);
}
} else if (ch == DOLLAR) {
- buffer.append(ESCAPE_CHAR).append(DOLLAR);
+ buf.append(ESCAPE_CHAR).append(DOLLAR);
} else {
throw new PatternSyntaxException("Syntax Error", pattern, i);
}
@@ -200,7 +209,7 @@ public static String classNameToRegex(String pattern, int options) throws Patter
}
}
- return buffer.toString();
+ return buf.toString();
}
/**
View
11 common/util/src/main/java/com/alibaba/citrus/util/regex/PathNameWildcardCompiler.java
@@ -67,6 +67,7 @@
private static final String REGEX_FILE_NAME = "(" + REGEX_FILE_NAME_CHAR + "*)";
private static final String REGEX_FILE_PATH = "(" + REGEX_FILE_NAME_CHAR + "+(?:" + REGEX_SLASH_NO_DUP
+ REGEX_FILE_NAME_CHAR + "*)*(?=" + REGEX_SLASH + "|$)|)" + REGEX_SLASH + "?";
+ private static final String REGEX_END_OF_PATH = "(?=" + REGEX_SLASH + "|$)" + REGEX_SLASH + "?";
// 上一个token的状态
private static final int LAST_TOKEN_START = 0;
@@ -191,8 +192,16 @@ public static String pathNameToRegex(String pattern, int options) throws Pattern
break;
case QUESTION:
+ if (lastToken == LAST_TOKEN_START) {
+ buf.append(REGEX_WORD_BOUNDARY).append(REGEX_FILE_NAME_SINGLE_CHAR); // 前边界
+ } else if (i + 1 == pattern.length()) {
+ buf.append(REGEX_FILE_NAME_SINGLE_CHAR).append(REGEX_END_OF_PATH); // 后边界
+ } else {
+ buf.append(REGEX_FILE_NAME_SINGLE_CHAR);
+ }
+
lastToken = LAST_TOKEN_QUESTION;
- buf.append(REGEX_FILE_NAME_SINGLE_CHAR);
+
break;
default:
View
25 common/util/src/test/java/com/alibaba/citrus/util/regex/WildcardCompilerTests.java
@@ -66,6 +66,19 @@ public void pathNameWildcard() throws Exception {
assertTrue(contains("/xxx/yyy", pattern, ""));
assertTrue(contains("/xxx/yyyzzz", pattern, "zzz"));
+ // 以?结束
+ pattern = PathNameWildcardCompiler.compilePathName("/xxx/yyy?");
+
+ assertTrue(contains("/xxx/yyyz", pattern, "z"));
+ assertTrue(contains("/xxx/yyyz/", pattern, "z"));
+ assertFalse(contains("/xxx/yyyzz", pattern));
+
+ // 以?开始
+ pattern = PathNameWildcardCompiler.compilePathName("?xxx/yyy");
+
+ assertTrue(contains("/zxxx/yyy", pattern, "z"));
+ assertFalse(contains("/zzxxx/yyy", pattern));
+
// 特殊处理
pattern = PathNameWildcardCompiler.compilePathName("/");
@@ -126,6 +139,18 @@ public void classNameWildcard() throws Exception {
assertTrue(contains("xxx.yyy", pattern, ""));
assertTrue(contains("xxx.yyyzzz", pattern, "zzz"));
+ // 以?结尾
+ pattern = ClassNameWildcardCompiler.compileClassName("xxx.yyy?");
+
+ assertTrue(contains("xxx.yyyz", pattern, "z"));
+ assertFalse(contains("xxx.yyyzz", pattern));
+
+ // 以?开始
+ pattern = ClassNameWildcardCompiler.compileClassName("?xxx.yyy");
+
+ assertTrue(contains("zxxx.yyy", pattern, "z"));
+ assertFalse(contains("zzxxx.yyy", pattern));
+
pattern = ClassNameWildcardCompiler.compileClassName("");
assertTrue(contains("", pattern));

0 comments on commit f696d31

Please sign in to comment.