diff --git a/src/main/java/com/ctrip/zeus/service/model/grammar/PathParseHandler.java b/src/main/java/com/ctrip/zeus/service/model/grammar/PathParseHandler.java index 8320208d..90011ffe 100644 --- a/src/main/java/com/ctrip/zeus/service/model/grammar/PathParseHandler.java +++ b/src/main/java/com/ctrip/zeus/service/model/grammar/PathParseHandler.java @@ -28,7 +28,7 @@ public class PathParseHandler { public String[] parse(String path) throws GrammarException { try { - return pathLookupCache.get(path.toCharArray()); + return pathLookupCache.get(extractUriIgnoresFirstDelimiter(PathUtils.pathReformat(path).toCharArray())); } catch (ExecutionException e) { if (e.getCause() instanceof GrammarException) { throw (GrammarException) e.getCause(); @@ -44,6 +44,48 @@ public class PathParseHandler { return root.toArray(new String[root.size()]); } + public static char[] extractUriIgnoresFirstDelimiter(char[] path) throws GrammarException { + int idxPrefix = 0; + int idxModifier = 0; + boolean quote = false; + + for (char c : path) { + if (c == '"') { + quote = true; + idxPrefix++; + } else if (c == ' ') { + idxPrefix++; + idxModifier = idxPrefix; + } else if (c == '^' || c == '~' || c == '=' || c == '*') { + idxPrefix++; + } else if (c == '/') { + idxPrefix++; + if (!quote && idxPrefix < path.length && path[idxPrefix] == '"') { + quote = true; + idxPrefix++; + } + break; + } else { + break; + } + } + + if (quote && path[path.length - 1] != '\"') { + throw new GrammarException("Missing end quote. " + "\"path\" : \"" + path + "\""); + } + int idxSuffix = quote ? path.length - 1 : path.length; + if (idxPrefix == idxSuffix) { + if (path[idxSuffix - 1] == '/') { + return new char[]{'/'}; + } else { + throw new GrammarException("Invalid uri after extraction. " + "\"path\" : \"" + path + "\""); + } + } + idxPrefix = idxPrefix < idxSuffix ? + (idxModifier > idxPrefix ? idxModifier : idxPrefix) : idxModifier; + return Arrays.copyOfRange(path, idxPrefix, idxSuffix); + } + private int enumeratePathValues(char[] pathArray, List prefix, int start, int depth, char startSymbol) throws GrammarException { StringBuilder pathBuilder = new StringBuilder(); int i = start; diff --git a/src/main/java/com/ctrip/zeus/service/model/grammar/PathUtils.java b/src/main/java/com/ctrip/zeus/service/model/grammar/PathUtils.java index 40e6a413..fd8f8388 100644 --- a/src/main/java/com/ctrip/zeus/service/model/grammar/PathUtils.java +++ b/src/main/java/com/ctrip/zeus/service/model/grammar/PathUtils.java @@ -62,29 +62,30 @@ public class PathUtils { return len1 > len2 ? 1 : 2; } - public static String pathReformat(String path) throws ValidationException { + public static String pathReformat(String path) throws GrammarException { int offset = 0; String[] pathValues = new String[2]; for (String pv : path.split(" ", 0)) { if (pv.isEmpty()) continue; if (offset >= 2) { - throw new ValidationException("Invalid number of path modifiers. Path reformat fails."); + throw new GrammarException("Invalid number of path modifiers. Path reformat fails."); } pathValues[offset] = pv; offset++; } if (offset == 0) { - throw new ValidationException("Empty path value. Path reformat fails."); + throw new GrammarException("Empty path value. Path reformat fails."); } if (offset == 2 && !pathPrefixModifier.contains(pathValues[0])) { - throw new ValidationException("Invalid path modifier. Path reformat fails."); + throw new GrammarException("Invalid path modifier. Path reformat fails."); } // format path value return offset == 1 ? pathValues[0] : pathValues[0] + " " + pathValues[1]; } + public static String extractUriIgnoresFirstDelimiter(String path) throws ValidationException { int idxPrefix = 0; int idxModifier = 0; diff --git a/src/test/java/com/ctrip/zeus/service/model/PathValidationTest.java b/src/test/java/com/ctrip/zeus/service/model/PathValidationTest.java index 3539b6c8..468eaed6 100644 --- a/src/test/java/com/ctrip/zeus/service/model/PathValidationTest.java +++ b/src/test/java/com/ctrip/zeus/service/model/PathValidationTest.java @@ -7,6 +7,7 @@ import com.ctrip.zeus.dal.core.RelGroupStatusDo; import com.ctrip.zeus.dal.core.RelGroupVsDo; import com.ctrip.zeus.exceptions.ValidationException; import com.ctrip.zeus.model.entity.*; +import com.ctrip.zeus.service.model.grammar.GrammarException; import com.ctrip.zeus.service.model.handler.GroupValidator; import com.ctrip.zeus.service.model.grammar.PathUtils; import com.google.common.collect.Sets; @@ -18,6 +19,7 @@ import org.unidal.dal.jdbc.DalException; import javax.annotation.Resource; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; /** @@ -40,7 +42,7 @@ public class PathValidationTest extends AbstractServerTest { private final String standardSuffix = "($|/|\\?)"; @Test - public void testExtractUriFromRegexPath() throws ValidationException { + public void testExtractUriFromRegexPath() throws Exception { String normalValue1 = "abc($|/|\\?)"; String normalValue2 = "abc"; String normalValue3 = "/abc"; @@ -74,7 +76,7 @@ public class PathValidationTest extends AbstractServerTest { } @Test - public void testPathUtils() throws ValidationException { + public void testPathUtils() throws Exception { String s1 = "abcdefg"; String s2 = "abc"; String s3 = extractUri("ABCDefghij($|/|\\?)"); @@ -439,7 +441,7 @@ public class PathValidationTest extends AbstractServerTest { } } - private static String extractUri(String path) throws ValidationException { + private static String extractUri(String path) throws Exception { path = PathUtils.pathReformat(path); return PathUtils.extractUriIgnoresFirstDelimiter(path); } diff --git a/src/test/java/com/ctrip/zeus/service/model/PathValidationV2Test.java b/src/test/java/com/ctrip/zeus/service/model/PathValidationV2Test.java index cbe1e5af..f7d5fcd7 100644 --- a/src/test/java/com/ctrip/zeus/service/model/PathValidationV2Test.java +++ b/src/test/java/com/ctrip/zeus/service/model/PathValidationV2Test.java @@ -16,7 +16,7 @@ import java.util.List; public class PathValidationV2Test { @Test - public void testExtractUriFromRegexPath() throws ValidationException { + public void testExtractUriFromRegexPath() throws Exception { String normalValue1 = "abc($|/|\\?)"; String normalValue2 = "abc"; String normalValue3 = "/abc"; @@ -49,9 +49,9 @@ public class PathValidationV2Test { Assert.assertEquals("/", extractUri(root5)); } - private static String extractUri(String path) throws ValidationException { - path = PathUtils.pathReformat(path); - return PathUtils.extractUriIgnoresFirstDelimiter(path); + private static String extractUri(String path) throws Exception { + PathUtils.pathReformat(path); + return new String(PathParseHandler.extractUriIgnoresFirstDelimiter(path.toCharArray())); } @Test