Skip to content

Commit a06da00

Browse files
committed
Remove PathPatternParser from PatternsRequestCondition
Since `PathPattern.combine` now returns another `PathPattern` instance (it was previously returning a String instance), we can now safely remove the parser instance included in `PatternsRequestCondition`. Issue: SPR-15663
1 parent 7a0e5a3 commit a06da00

File tree

4 files changed

+90
-76
lines changed

4 files changed

+90
-76
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/PatternsRequestCondition.java

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,18 @@
1919
import java.util.ArrayList;
2020
import java.util.Arrays;
2121
import java.util.Collection;
22-
import java.util.Collections;
2322
import java.util.Comparator;
2423
import java.util.Iterator;
2524
import java.util.List;
2625
import java.util.Set;
2726
import java.util.SortedSet;
2827
import java.util.TreeSet;
2928
import java.util.stream.Collectors;
30-
import java.util.stream.Stream;
3129

3230
import org.springframework.http.server.reactive.PathContainer;
3331
import org.springframework.lang.Nullable;
34-
import org.springframework.util.StringUtils;
3532
import org.springframework.web.server.ServerWebExchange;
3633
import org.springframework.web.util.pattern.PathPattern;
37-
import org.springframework.web.util.pattern.PathPatternParser;
3834

3935
/**
4036
* A logical disjunction (' || ') request condition that matches a request
@@ -46,48 +42,32 @@
4642
*/
4743
public final class PatternsRequestCondition extends AbstractRequestCondition<PatternsRequestCondition> {
4844

49-
private final Set<PathPattern> patterns;
50-
51-
private final PathPatternParser parser;
45+
private final SortedSet<PathPattern> patterns;
5246

5347

5448
/**
5549
* Creates a new instance with the given URL patterns.
56-
* Each pattern is prepended with "/" if not already.
5750
* @param patterns 0 or more URL patterns; if 0 the condition will match to every request.
5851
*/
59-
public PatternsRequestCondition(String... patterns) {
60-
this(patterns, null);
52+
public PatternsRequestCondition(PathPattern... patterns) {
53+
this(Arrays.asList(patterns));
6154
}
6255

6356
/**
64-
* Creates a new instance with the given URL patterns.
65-
* Each pattern that is not empty and does not start with "/" is pre-pended with "/".
66-
* @param patterns the URL patterns to use; if 0, the condition will match to every request.
67-
* @param patternParser for parsing string patterns
57+
* Creates a new instance with the given {@code Stream} of URL patterns.
6858
*/
69-
public PatternsRequestCondition(String[] patterns, PathPatternParser patternParser) {
70-
this(Arrays.asList(patterns), patternParser);
59+
public PatternsRequestCondition(List<PathPattern> patterns) {
60+
this(toSortedSet(patterns));
7161
}
7262

73-
/**
74-
* Private constructor accepting a collection of raw patterns.
75-
*/
76-
private PatternsRequestCondition(Collection<String> patterns, PathPatternParser parser) {
77-
this.parser = (parser != null ? parser : new PathPatternParser());
78-
this.patterns = toSortedSet(patterns.stream().map(pattern -> parse(pattern, this.parser)));
79-
}
80-
81-
private static PathPattern parse(String pattern, PathPatternParser parser) {
82-
if (StringUtils.hasText(pattern) && !pattern.startsWith("/")) {
83-
pattern = "/" + pattern;
84-
}
85-
return parser.parse(pattern);
63+
private static SortedSet<PathPattern> toSortedSet(Collection<PathPattern> patterns) {
64+
TreeSet<PathPattern> sorted = new TreeSet<>(getPatternComparator());
65+
sorted.addAll(patterns);
66+
return sorted;
8667
}
8768

88-
private static Set<PathPattern> toSortedSet(Stream<PathPattern> stream) {
89-
return Collections.unmodifiableSet(stream.sorted()
90-
.collect(Collectors.toCollection(() -> new TreeSet<>(getPatternComparator()))));
69+
private PatternsRequestCondition(SortedSet<PathPattern> patterns) {
70+
this.patterns = patterns;
9171
}
9272

9373
private static Comparator<PathPattern> getPatternComparator() {
@@ -97,14 +77,6 @@ private static Comparator<PathPattern> getPatternComparator() {
9777
};
9878
}
9979

100-
/**
101-
* Private constructor accepting a list of path patterns.
102-
*/
103-
private PatternsRequestCondition(List<PathPattern> patterns, PathPatternParser patternParser) {
104-
this.patterns = toSortedSet(patterns.stream());
105-
this.parser = patternParser;
106-
}
107-
10880
public Set<PathPattern> getPatterns() {
10981
return this.patterns;
11082
}
@@ -145,10 +117,7 @@ else if (!this.patterns.isEmpty()) {
145117
else if (!other.patterns.isEmpty()) {
146118
combined.addAll(other.patterns);
147119
}
148-
else {
149-
combined.add(this.parser.parse(""));
150-
}
151-
return new PatternsRequestCondition(combined, this.parser);
120+
return new PatternsRequestCondition(combined);
152121
}
153122

154123
/**
@@ -167,7 +136,7 @@ public PatternsRequestCondition getMatchingCondition(ServerWebExchange exchange)
167136
}
168137
SortedSet<PathPattern> matches = getMatchingPatterns(exchange);
169138
return matches.isEmpty() ? null :
170-
new PatternsRequestCondition(new ArrayList<PathPattern>(matches), this.parser);
139+
new PatternsRequestCondition(matches);
171140
}
172141

173142
/**

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfo.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package org.springframework.web.reactive.result.method;
1818

19+
import java.util.Arrays;
20+
import java.util.List;
21+
import java.util.stream.Collectors;
22+
1923
import org.springframework.lang.Nullable;
2024
import org.springframework.util.StringUtils;
2125
import org.springframework.web.bind.annotation.RequestMethod;
@@ -29,6 +33,7 @@
2933
import org.springframework.web.reactive.result.condition.RequestConditionHolder;
3034
import org.springframework.web.reactive.result.condition.RequestMethodsRequestCondition;
3135
import org.springframework.web.server.ServerWebExchange;
36+
import org.springframework.web.util.pattern.PathPattern;
3237
import org.springframework.web.util.pattern.PathPatternParser;
3338

3439
/**
@@ -478,8 +483,9 @@ public Builder options(BuilderConfiguration options) {
478483
public RequestMappingInfo build() {
479484
RequestedContentTypeResolver contentTypeResolver = this.options.getContentTypeResolver();
480485

481-
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
482-
this.paths, this.options.getPatternParser());
486+
PathPatternParser parser = this.options.getPatternParser() != null ?
487+
this.options.getPatternParser() : new PathPatternParser();
488+
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(parse(this.paths, parser));
483489

484490
return new RequestMappingInfo(this.mappingName, patternsCondition,
485491
new RequestMethodsRequestCondition(methods),
@@ -489,6 +495,18 @@ public RequestMappingInfo build() {
489495
new ProducesRequestCondition(this.produces, this.headers, contentTypeResolver),
490496
this.customCondition);
491497
}
498+
499+
private static List<PathPattern> parse(String[] paths, PathPatternParser parser) {
500+
return Arrays
501+
.stream(paths)
502+
.map(path -> {
503+
if (StringUtils.hasText(path) && !path.startsWith("/")) {
504+
path = "/" + path;
505+
}
506+
return parser.parse(path);
507+
})
508+
.collect(Collectors.toList());
509+
}
492510
}
493511

494512

spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/PatternsRequestConditionTests.java

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Arrays;
2020
import java.util.Iterator;
21+
import java.util.stream.Collectors;
2122

2223
import org.junit.Test;
2324

@@ -38,15 +39,11 @@
3839
*/
3940
public class PatternsRequestConditionTests {
4041

41-
@Test
42-
public void prependSlash() {
43-
PatternsRequestCondition c = new PatternsRequestCondition("foo");
44-
assertEquals("/foo", c.getPatterns().iterator().next().getPatternString());
45-
}
42+
private final PathPatternParser parser = new PathPatternParser();
4643

4744
@Test
4845
public void prependNonEmptyPatternsOnly() {
49-
PatternsRequestCondition c = new PatternsRequestCondition("");
46+
PatternsRequestCondition c = createPatternsCondition("");
5047
assertEquals("Do not prepend empty patterns (SPR-8255)", "",
5148
c.getPatterns().iterator().next().getPatternString());
5249
}
@@ -56,51 +53,51 @@ public void combineEmptySets() {
5653
PatternsRequestCondition c1 = new PatternsRequestCondition();
5754
PatternsRequestCondition c2 = new PatternsRequestCondition();
5855

59-
assertEquals(new PatternsRequestCondition(""), c1.combine(c2));
56+
assertEquals(createPatternsCondition(), c1.combine(c2));
6057
}
6158

6259
@Test
6360
public void combineOnePatternWithEmptySet() {
64-
PatternsRequestCondition c1 = new PatternsRequestCondition("/type1", "/type2");
61+
PatternsRequestCondition c1 = createPatternsCondition("/type1", "/type2");
6562
PatternsRequestCondition c2 = new PatternsRequestCondition();
6663

67-
assertEquals(new PatternsRequestCondition("/type1", "/type2"), c1.combine(c2));
64+
assertEquals(createPatternsCondition("/type1", "/type2"), c1.combine(c2));
6865

6966
c1 = new PatternsRequestCondition();
70-
c2 = new PatternsRequestCondition("/method1", "/method2");
67+
c2 = createPatternsCondition("/method1", "/method2");
7168

72-
assertEquals(new PatternsRequestCondition("/method1", "/method2"), c1.combine(c2));
69+
assertEquals(createPatternsCondition("/method1", "/method2"), c1.combine(c2));
7370
}
7471

7572
@Test
7673
public void combineMultiplePatterns() {
77-
PatternsRequestCondition c1 = new PatternsRequestCondition("/t1", "/t2");
78-
PatternsRequestCondition c2 = new PatternsRequestCondition("/m1", "/m2");
74+
PatternsRequestCondition c1 = createPatternsCondition("/t1", "/t2");
75+
PatternsRequestCondition c2 = createPatternsCondition("/m1", "/m2");
7976

80-
assertEquals(new PatternsRequestCondition("/t1/m1", "/t1/m2", "/t2/m1", "/t2/m2"), c1.combine(c2));
77+
assertEquals(createPatternsCondition("/t1/m1", "/t1/m2", "/t2/m1", "/t2/m2"), c1.combine(c2));
8178
}
8279

8380
@Test
8481
public void matchDirectPath() throws Exception {
85-
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
82+
PatternsRequestCondition condition = createPatternsCondition("/foo");
8683
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo").toExchange());
8784

8885
assertNotNull(match);
8986
}
9087

9188
@Test
9289
public void matchPattern() throws Exception {
93-
PatternsRequestCondition condition = new PatternsRequestCondition("/foo/*");
90+
PatternsRequestCondition condition = createPatternsCondition("/foo/*");
9491
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo/bar").toExchange());
9592

9693
assertNotNull(match);
9794
}
9895

9996
@Test
10097
public void matchSortPatterns() throws Exception {
101-
PatternsRequestCondition condition = new PatternsRequestCondition("/*/*", "/foo/bar", "/foo/*");
98+
PatternsRequestCondition condition = createPatternsCondition("/*/*", "/foo/bar", "/foo/*");
10299
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo/bar").toExchange());
103-
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/*/*");
100+
PatternsRequestCondition expected = createPatternsCondition("/foo/bar", "/foo/*", "/*/*");
104101

105102
assertEquals(expected, match);
106103
}
@@ -109,14 +106,14 @@ public void matchSortPatterns() throws Exception {
109106
public void matchTrailingSlash() throws Exception {
110107
MockServerWebExchange exchange = get("/foo/").toExchange();
111108

112-
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
109+
PatternsRequestCondition condition = createPatternsCondition("/foo");
113110
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
114111

115112
assertNotNull(match);
116113
assertEquals("Should match by default", "/foo",
117114
match.getPatterns().iterator().next().getPatternString());
118115

119-
condition = new PatternsRequestCondition(new String[] {"/foo"}, null);
116+
condition = createPatternsCondition("/foo");
120117
match = condition.getMatchingCondition(exchange);
121118

122119
assertNotNull(match);
@@ -125,31 +122,31 @@ public void matchTrailingSlash() throws Exception {
125122

126123
PathPatternParser parser = new PathPatternParser();
127124
parser.setMatchOptionalTrailingSlash(false);
128-
condition = new PatternsRequestCondition(new String[] {"/foo"}, parser);
125+
condition = new PatternsRequestCondition(parser.parse("/foo"));
129126
match = condition.getMatchingCondition(get("/foo/").toExchange());
130127

131128
assertNull(match);
132129
}
133130

134131
@Test
135132
public void matchPatternContainsExtension() throws Exception {
136-
PatternsRequestCondition condition = new PatternsRequestCondition("/foo.jpg");
133+
PatternsRequestCondition condition = createPatternsCondition("/foo.jpg");
137134
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo.html").toExchange());
138135

139136
assertNull(match);
140137
}
141138

142139
@Test
143140
public void compareEqualPatterns() throws Exception {
144-
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*");
145-
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo*");
141+
PatternsRequestCondition c1 = createPatternsCondition("/foo*");
142+
PatternsRequestCondition c2 = createPatternsCondition("/foo*");
146143

147144
assertEquals(0, c1.compareTo(c2, get("/foo").toExchange()));
148145
}
149146

150147
@Test
151148
public void equallyMatchingPatternsAreBothPresent() throws Exception {
152-
PatternsRequestCondition c = new PatternsRequestCondition("/a", "/b");
149+
PatternsRequestCondition c = createPatternsCondition("/a", "/b");
153150
assertEquals(2, c.getPatterns().size());
154151
Iterator<PathPattern> itr = c.getPatterns().iterator();
155152
assertEquals("/a", itr.next().getPatternString());
@@ -158,8 +155,8 @@ public void equallyMatchingPatternsAreBothPresent() throws Exception {
158155

159156
@Test
160157
public void comparePatternSpecificity() throws Exception {
161-
PatternsRequestCondition c1 = new PatternsRequestCondition("/fo*");
162-
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo");
158+
PatternsRequestCondition c1 = createPatternsCondition("/fo*");
159+
PatternsRequestCondition c2 = createPatternsCondition("/foo");
163160

164161
assertEquals(1, c1.compareTo(c2, get("/foo").toExchange()));
165162
}
@@ -168,8 +165,8 @@ public void comparePatternSpecificity() throws Exception {
168165
public void compareNumberOfMatchingPatterns() throws Exception {
169166
ServerWebExchange exchange = get("/foo.html").toExchange();
170167

171-
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo.*", "/foo.jpeg");
172-
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo.*", "/foo.html");
168+
PatternsRequestCondition c1 = createPatternsCondition("/foo.*", "/foo.jpeg");
169+
PatternsRequestCondition c2 = createPatternsCondition("/foo.*", "/foo.html");
173170

174171
PatternsRequestCondition match1 = c1.getMatchingCondition(exchange);
175172
PatternsRequestCondition match2 = c2.getMatchingCondition(exchange);
@@ -178,4 +175,11 @@ public void compareNumberOfMatchingPatterns() throws Exception {
178175
assertEquals(1, match1.compareTo(match2, exchange));
179176
}
180177

178+
private PatternsRequestCondition createPatternsCondition(String... patterns) {
179+
return new PatternsRequestCondition(Arrays
180+
.stream(patterns)
181+
.map(rawPattern -> this.parser.parse(rawPattern))
182+
.collect(Collectors.toList()));
183+
}
184+
181185
}

0 commit comments

Comments
 (0)