Skip to content

Commit 6791f32

Browse files
chschujzheaux
authored andcommitted
Add factory class for RequestMatcher composition
Closes gh-12751
1 parent dfdadc9 commit 6791f32

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.web.util.matcher;
18+
19+
import java.util.List;
20+
21+
/**
22+
* A factory class to create {@link RequestMatcher} instances.
23+
*
24+
* @author Christian Schuster
25+
* @since 6.1
26+
*/
27+
public final class RequestMatchers {
28+
29+
/**
30+
* Creates a {@link RequestMatcher} that matches if at least one of the given
31+
* {@link RequestMatcher}s matches, if <code>matchers</code> are empty then the
32+
* returned matcher never matches.
33+
* @param matchers the {@link RequestMatcher}s to use
34+
* @return the any-of composed {@link RequestMatcher}
35+
* @see OrRequestMatcher
36+
*/
37+
public static RequestMatcher anyOf(RequestMatcher... matchers) {
38+
return (matchers.length > 0) ? new OrRequestMatcher(List.of(matchers)) : (request) -> false;
39+
}
40+
41+
/**
42+
* Creates a {@link RequestMatcher} that matches if all the given
43+
* {@link RequestMatcher}s match, if <code>matchers</code> are empty then the returned
44+
* matcher always matches.
45+
* @param matchers the {@link RequestMatcher}s to use
46+
* @return the all-of composed {@link RequestMatcher}
47+
* @see AndRequestMatcher
48+
*/
49+
public static RequestMatcher allOf(RequestMatcher... matchers) {
50+
return (matchers.length > 0) ? new AndRequestMatcher(List.of(matchers)) : (request) -> true;
51+
}
52+
53+
/**
54+
* Creates a {@link RequestMatcher} that matches if the given {@link RequestMatcher}
55+
* does not match.
56+
* @param matcher the {@link RequestMatcher} to use
57+
* @return the inverted {@link RequestMatcher}
58+
*/
59+
public static RequestMatcher not(RequestMatcher matcher) {
60+
return (request) -> !matcher.matches(request);
61+
}
62+
63+
private RequestMatchers() {
64+
}
65+
66+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.web.util.matcher;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
23+
/**
24+
* Tests for {@link RequestMatchers}.
25+
*
26+
* @author Christian Schuster
27+
*/
28+
class RequestMatchersTests {
29+
30+
@Test
31+
void checkAnyOfWhenOneMatchThenMatch() {
32+
RequestMatcher composed = RequestMatchers.anyOf((r) -> false, (r) -> true);
33+
boolean match = composed.matches(null);
34+
assertThat(match).isTrue();
35+
}
36+
37+
@Test
38+
void checkAnyOfWhenNoneMatchThenNotMatch() {
39+
RequestMatcher composed = RequestMatchers.anyOf((r) -> false, (r) -> false);
40+
boolean match = composed.matches(null);
41+
assertThat(match).isFalse();
42+
}
43+
44+
@Test
45+
void checkAnyOfWhenEmptyThenNotMatch() {
46+
RequestMatcher composed = RequestMatchers.anyOf();
47+
boolean match = composed.matches(null);
48+
assertThat(match).isFalse();
49+
}
50+
51+
@Test
52+
void checkAllOfWhenOneNotMatchThenNotMatch() {
53+
RequestMatcher composed = RequestMatchers.allOf((r) -> false, (r) -> true);
54+
boolean match = composed.matches(null);
55+
assertThat(match).isFalse();
56+
}
57+
58+
@Test
59+
void checkAllOfWhenAllMatchThenMatch() {
60+
RequestMatcher composed = RequestMatchers.allOf((r) -> true, (r) -> true);
61+
boolean match = composed.matches(null);
62+
assertThat(match).isTrue();
63+
}
64+
65+
@Test
66+
void checkAllOfWhenEmptyThenMatch() {
67+
RequestMatcher composed = RequestMatchers.allOf();
68+
boolean match = composed.matches(null);
69+
assertThat(match).isTrue();
70+
}
71+
72+
@Test
73+
void checkNotWhenMatchThenNotMatch() {
74+
RequestMatcher composed = RequestMatchers.not((r) -> true);
75+
boolean match = composed.matches(null);
76+
assertThat(match).isFalse();
77+
}
78+
79+
@Test
80+
void checkNotWhenNotMatchThenMatch() {
81+
RequestMatcher composed = RequestMatchers.not((r) -> false);
82+
boolean match = composed.matches(null);
83+
assertThat(match).isTrue();
84+
}
85+
86+
}

0 commit comments

Comments
 (0)