diff --git a/org.springframework.core/src/main/java/org/springframework/util/AntPatchStringMatcher.java b/org.springframework.core/src/main/java/org/springframework/util/AntPatchStringMatcher.java index 013d3ce02c7..b747bee726f 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/AntPatchStringMatcher.java +++ b/org.springframework.core/src/main/java/org/springframework/util/AntPatchStringMatcher.java @@ -28,12 +28,7 @@ class AntPatchStringMatcher { private final Map uriTemplateVariables; - /** - * Constructs a new instance of the AntPatchStringMatcher. - * @param pattern - * @param str - * @param uriTemplateVariables - */ + /** Constructs a new instance of the AntPatchStringMatcher. */ AntPatchStringMatcher(String pattern, String str, Map uriTemplateVariables) { patArr = pattern.toCharArray(); strArr = str.toCharArray(); @@ -42,12 +37,6 @@ class AntPatchStringMatcher { strIdxEnd = strArr.length - 1; } - private void addTemplateVariable(String varName, String varValue) { - if (uriTemplateVariables != null) { - uriTemplateVariables.put(varName, varValue); - } - } - private void addTemplateVariable(int curlyIdxStart, int curlyIdxEnd, int valIdxStart, int valIdxEnd) { if (uriTemplateVariables != null) { String varName = new String(patArr, curlyIdxStart + 1, curlyIdxEnd - curlyIdxStart - 1); @@ -56,6 +45,11 @@ class AntPatchStringMatcher { } } + /** + * Main entry point. + * + * @return true if the string matches against the pattern, or false otherwise. + */ boolean matchStrings() { if (shortcutPossible()) { return doShortcut(); @@ -82,10 +76,16 @@ class AntPatchStringMatcher { // process pattern between stars. padIdxStart and patIdxEnd point // always to a '*'. while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { - int patIdxTmp = findNextStar(); - if (patIdxTmp == patIdxStart + 1 && patArr[patIdxTmp] == '*') { - // Two stars next to each other, skip the first one. - patIdxStart++; + int patIdxTmp; + if (patArr[patIdxStart] == '{') { + patIdxTmp = findClosingCurly(); + addTemplateVariable(patIdxStart, patIdxTmp, strIdxStart, strIdxEnd); + patIdxStart = patIdxTmp + 1; + strIdxStart = strIdxEnd + 1; + continue; + } + patIdxTmp = findNextStarOrCurly(); + if (consecutiveStars(patIdxTmp)) { continue; } // Find the pattern between padIdxStart & padIdxTmp in str between @@ -119,9 +119,27 @@ class AntPatchStringMatcher { return onlyStarsLeft(); } - private int findNextStar() { + private boolean consecutiveStars(int patIdxTmp) { + if (patIdxTmp == patIdxStart + 1 && patArr[patIdxStart] == '*' && patArr[patIdxTmp] == '*') { + // Two stars next to each other, skip the first one. + patIdxStart++; + return true; + } + return false; + } + + private int findNextStarOrCurly() { + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*' || patArr[i] == '{') { + return i; + } + } + return -1; + } + + private int findClosingCurly() { for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { - if (patArr[i] == '*') { + if (patArr[i] == '}') { return i; } } diff --git a/org.springframework.core/src/test/java/org/springframework/util/AntPathMatcherTests.java b/org.springframework.core/src/test/java/org/springframework/util/AntPathMatcherTests.java index 3fe76a28d3b..5f05cd4a4a5 100644 --- a/org.springframework.core/src/test/java/org/springframework/util/AntPathMatcherTests.java +++ b/org.springframework.core/src/test/java/org/springframework/util/AntPathMatcherTests.java @@ -295,7 +295,11 @@ public class AntPathMatcherTests { @Test public void extractUriTemplateVariables() throws Exception { - Map result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}", "/hotels/1"); + Map result; + result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}", "/hotels/1"); + assertEquals(Collections.singletonMap("hotel", "1"), result); + + result = pathMatcher.extractUriTemplateVariables("/h?tels/{hotel}", "/hotels/1"); assertEquals(Collections.singletonMap("hotel", "1"), result); result = pathMatcher.extractUriTemplateVariables("/hotels/{hotel}/bookings/{booking}", "/hotels/1/bookings/2"); @@ -306,6 +310,12 @@ public class AntPathMatcherTests { result = pathMatcher.extractUriTemplateVariables("/**/hotels/**/{hotel}", "/foo/hotels/bar/1"); assertEquals(Collections.singletonMap("hotel", "1"), result); + + result = pathMatcher.extractUriTemplateVariables("/{page}.html", "/42.html"); + assertEquals(Collections.singletonMap("page", "42"), result); + + result = pathMatcher.extractUriTemplateVariables("/A-{B}-C", "/A-b-C"); + assertEquals(Collections.singletonMap("B", "b"), result); }