Merge branch '6.2.x'
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,13 +37,24 @@ public abstract class PatternMatchUtils {
|
||||
* @return whether the String matches the given pattern
|
||||
*/
|
||||
public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) {
|
||||
return simpleMatch(pattern, str, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #simpleMatch(String, String)} that ignores upper/lower case.
|
||||
*/
|
||||
public static boolean simpleMatchIgnoreCase(@Nullable String pattern, @Nullable String str) {
|
||||
return simpleMatch(pattern, str, true);
|
||||
}
|
||||
|
||||
private static boolean simpleMatch(@Nullable String pattern, @Nullable String str, boolean ignoreCase) {
|
||||
if (pattern == null || str == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int firstIndex = pattern.indexOf('*');
|
||||
if (firstIndex == -1) {
|
||||
return pattern.equals(str);
|
||||
return (ignoreCase ? pattern.equalsIgnoreCase(str) : pattern.equals(str));
|
||||
}
|
||||
|
||||
if (firstIndex == 0) {
|
||||
@@ -52,25 +63,43 @@ public abstract class PatternMatchUtils {
|
||||
}
|
||||
int nextIndex = pattern.indexOf('*', 1);
|
||||
if (nextIndex == -1) {
|
||||
return str.endsWith(pattern.substring(1));
|
||||
String part = pattern.substring(1);
|
||||
return (ignoreCase ? StringUtils.endsWithIgnoreCase(str, part) : str.endsWith(part));
|
||||
}
|
||||
String part = pattern.substring(1, nextIndex);
|
||||
if (part.isEmpty()) {
|
||||
return simpleMatch(pattern.substring(nextIndex), str);
|
||||
return simpleMatch(pattern.substring(nextIndex), str, ignoreCase);
|
||||
}
|
||||
int partIndex = str.indexOf(part);
|
||||
int partIndex = indexOf(str, part, 0, ignoreCase);
|
||||
while (partIndex != -1) {
|
||||
if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
|
||||
if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()), ignoreCase)) {
|
||||
return true;
|
||||
}
|
||||
partIndex = str.indexOf(part, partIndex + 1);
|
||||
partIndex = indexOf(str, part, partIndex + 1, ignoreCase);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return (str.length() >= firstIndex &&
|
||||
pattern.startsWith(str.substring(0, firstIndex)) &&
|
||||
simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
|
||||
checkStartsWith(pattern, str, firstIndex, ignoreCase) &&
|
||||
simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex), ignoreCase));
|
||||
}
|
||||
|
||||
private static boolean checkStartsWith(String pattern, String str, int index, boolean ignoreCase) {
|
||||
String part = str.substring(0, index);
|
||||
return (ignoreCase ? StringUtils.startsWithIgnoreCase(pattern, part) : pattern.startsWith(part));
|
||||
}
|
||||
|
||||
private static int indexOf(String str, String otherStr, int startIndex, boolean ignoreCase) {
|
||||
if (!ignoreCase) {
|
||||
return str.indexOf(otherStr, startIndex);
|
||||
}
|
||||
for (int i = startIndex; i <= (str.length() - otherStr.length()); i++) {
|
||||
if (str.regionMatches(true, i, otherStr, 0, otherStr.length())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,4 +123,18 @@ public abstract class PatternMatchUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #simpleMatch(String[], String)} that ignores upper/lower case.
|
||||
*/
|
||||
public static boolean simpleMatchIgnoreCase(@Nullable String[] patterns, @Nullable String str) {
|
||||
if (patterns != null) {
|
||||
for (String pattern : patterns) {
|
||||
if (simpleMatch(pattern, str, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,18 +53,22 @@ class PatternMatchUtilsTests {
|
||||
assertMatches(new String[] { null, "" }, "");
|
||||
assertMatches(new String[] { null, "123" }, "123");
|
||||
assertMatches(new String[] { null, "*" }, "123");
|
||||
|
||||
testMixedCaseMatch("abC", "Abc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void startsWith() {
|
||||
assertMatches("get*", "getMe");
|
||||
assertDoesNotMatch("get*", "setMe");
|
||||
testMixedCaseMatch("geT*", "GetMe");
|
||||
}
|
||||
|
||||
@Test
|
||||
void endsWith() {
|
||||
assertMatches("*Test", "getMeTest");
|
||||
assertDoesNotMatch("*Test", "setMe");
|
||||
testMixedCaseMatch("*TeSt", "getMeTesT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,6 +78,10 @@ class PatternMatchUtilsTests {
|
||||
assertMatches("*stuff*", "stuffTest");
|
||||
assertMatches("*stuff*", "getstuff");
|
||||
assertMatches("*stuff*", "stuff");
|
||||
testMixedCaseMatch("*stuff*", "getStuffTest");
|
||||
testMixedCaseMatch("*stuff*", "StuffTest");
|
||||
testMixedCaseMatch("*stuff*", "getStuff");
|
||||
testMixedCaseMatch("*stuff*", "Stuff");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,6 +90,8 @@ class PatternMatchUtilsTests {
|
||||
assertMatches("on*Event", "onEvent");
|
||||
assertDoesNotMatch("3*3", "3");
|
||||
assertMatches("3*3", "33");
|
||||
testMixedCaseMatch("on*Event", "OnMyEvenT");
|
||||
testMixedCaseMatch("on*Event", "OnEvenT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,18 +132,27 @@ class PatternMatchUtilsTests {
|
||||
|
||||
private void assertMatches(String pattern, String str) {
|
||||
assertThat(PatternMatchUtils.simpleMatch(pattern, str)).isTrue();
|
||||
assertThat(PatternMatchUtils.simpleMatchIgnoreCase(pattern, str)).isTrue();
|
||||
}
|
||||
|
||||
private void assertDoesNotMatch(String pattern, String str) {
|
||||
assertThat(PatternMatchUtils.simpleMatch(pattern, str)).isFalse();
|
||||
assertThat(PatternMatchUtils.simpleMatchIgnoreCase(pattern, str)).isFalse();
|
||||
}
|
||||
|
||||
private void testMixedCaseMatch(String pattern, String str) {
|
||||
assertThat(PatternMatchUtils.simpleMatch(pattern, str)).isFalse();
|
||||
assertThat(PatternMatchUtils.simpleMatchIgnoreCase(pattern, str)).isTrue();
|
||||
}
|
||||
|
||||
private void assertMatches(String[] patterns, String str) {
|
||||
assertThat(PatternMatchUtils.simpleMatch(patterns, str)).isTrue();
|
||||
assertThat(PatternMatchUtils.simpleMatchIgnoreCase(patterns, str)).isTrue();
|
||||
}
|
||||
|
||||
private void assertDoesNotMatch(String[] patterns, String str) {
|
||||
assertThat(PatternMatchUtils.simpleMatch(patterns, str)).isFalse();
|
||||
assertThat(PatternMatchUtils.simpleMatchIgnoreCase(patterns, str)).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -443,11 +443,10 @@ final class HierarchicalUriComponents extends UriComponents {
|
||||
UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables);
|
||||
this.queryParams.forEach((key, values) -> {
|
||||
String name = expandUriComponent(key, queryVariables, this.variableEncoder);
|
||||
List<String> expandedValues = new ArrayList<>(values.size());
|
||||
List<String> expandedValues = result.computeIfAbsent(name, k -> new ArrayList<>(values.size()));
|
||||
for (String value : values) {
|
||||
expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder));
|
||||
}
|
||||
result.put(name, expandedValues);
|
||||
});
|
||||
return CollectionUtils.unmodifiableMultiValueMap(result);
|
||||
}
|
||||
|
||||
@@ -629,6 +629,17 @@ class UriComponentsBuilderTests {
|
||||
assertThat(uri.toString()).isEqualTo("ws://example.org:7777/path?q=1#foo");
|
||||
}
|
||||
|
||||
@ParameterizedTest // gh-34783
|
||||
@EnumSource
|
||||
void parseBuildAndExpandQueryParamWithSameName(ParserType parserType) {
|
||||
UriComponents result = UriComponentsBuilder
|
||||
.fromUriString("/?{pk1}={pv1}&{pk2}={pv2}", parserType)
|
||||
.buildAndExpand("k1", "v1", "k1", "v2");
|
||||
|
||||
assertThat(result.getQuery()).isEqualTo("k1=v1&k1=v2");
|
||||
assertThat(result.getQueryParams()).containsExactly(Map.entry("k1", List.of("v1", "v2")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource
|
||||
void buildAndExpandOpaque(ParserType parserType) {
|
||||
|
||||
Reference in New Issue
Block a user