Skip to content

Commit a98baa7

Browse files
committed
Polish ServletRegistration API Deferral
Tomcat uses different ServletContext instances from startup- and request-time. This commit ensures that if the programmatic API isn't available at startup-time, then use the ServletContext attached to the HttpServletRequest at runtime. Issue gh-13794
1 parent bb0987d commit a98baa7

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.util.List;
2424
import java.util.Map;
2525
import java.util.concurrent.atomic.AtomicReference;
26-
import java.util.function.Supplier;
26+
import java.util.function.Function;
2727

2828
import javax.servlet.DispatcherType;
2929
import javax.servlet.ServletContext;
@@ -44,7 +44,6 @@
4444
import org.springframework.security.web.util.matcher.RequestMatcher;
4545
import org.springframework.util.Assert;
4646
import org.springframework.util.ClassUtils;
47-
import org.springframework.util.function.SingletonSupplier;
4847
import org.springframework.web.context.WebApplicationContext;
4948
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
5049

@@ -327,7 +326,8 @@ public C requestMatchers(HttpMethod method, String... patterns) {
327326
matchers.add(resolve(ant, mvc, servletContext));
328327
}
329328
else {
330-
matchers.add(new DeferredRequestMatcher(() -> resolve(ant, mvc, servletContext), mvc, ant));
329+
matchers.add(new DeferredRequestMatcher((request) -> resolve(ant, mvc, request.getServletContext()),
330+
mvc, ant));
331331
}
332332
}
333333
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
@@ -584,27 +584,34 @@ static List<RequestMatcher> regexMatchers(String... regexPatterns) {
584584

585585
static class DeferredRequestMatcher implements RequestMatcher {
586586

587-
final Supplier<RequestMatcher> requestMatcher;
587+
final Function<HttpServletRequest, RequestMatcher> requestMatcherFactory;
588588

589589
final AtomicReference<String> description = new AtomicReference<>();
590590

591-
DeferredRequestMatcher(Supplier<RequestMatcher> resolver, RequestMatcher... candidates) {
592-
this.requestMatcher = SingletonSupplier.of(() -> {
593-
RequestMatcher matcher = resolver.get();
594-
this.description.set(matcher.toString());
595-
return matcher;
596-
});
591+
volatile RequestMatcher requestMatcher;
592+
593+
DeferredRequestMatcher(Function<HttpServletRequest, RequestMatcher> resolver, RequestMatcher... candidates) {
594+
this.requestMatcherFactory = (request) -> {
595+
if (this.requestMatcher == null) {
596+
synchronized (this) {
597+
if (this.requestMatcher == null) {
598+
this.requestMatcher = resolver.apply(request);
599+
}
600+
}
601+
}
602+
return this.requestMatcher;
603+
};
597604
this.description.set("Deferred " + Arrays.toString(candidates));
598605
}
599606

600607
@Override
601608
public boolean matches(HttpServletRequest request) {
602-
return this.requestMatcher.get().matches(request);
609+
return this.requestMatcherFactory.apply(request).matches(request);
603610
}
604611

605612
@Override
606613
public MatchResult matcher(HttpServletRequest request) {
607-
return this.requestMatcher.get().matcher(request);
614+
return this.requestMatcherFactory.apply(request).matcher(request);
608615
}
609616

610617
@Override

config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ private static List<RequestMatcher> unwrap(List<RequestMatcher> wrappedMatchers)
385385
List<RequestMatcher> requestMatchers = new ArrayList<>();
386386
for (RequestMatcher requestMatcher : wrappedMatchers) {
387387
if (requestMatcher instanceof AbstractRequestMatcherRegistry.DeferredRequestMatcher) {
388-
requestMatchers.add(((DeferredRequestMatcher) requestMatcher).requestMatcher.get());
388+
requestMatchers.add(((DeferredRequestMatcher) requestMatcher).requestMatcher);
389389
}
390390
else {
391391
requestMatchers.add(requestMatcher);

0 commit comments

Comments
 (0)