Commit d6649678 authored by Phillip Webb's avatar Phillip Webb

Propagate exceptions in security matchers

Update `ApplicationContextRequestMatcher` and
`ApplicationContextServerWebExchangeMatcher` to use a supplier for
the context, rather than the context itself.

This allow exceptions to be propagated to subclasses which may choose
to deal with them.

See gh-12238
parent 802cd856
...@@ -23,6 +23,7 @@ import java.util.LinkedHashSet; ...@@ -23,6 +23,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -132,10 +133,10 @@ public final class EndpointRequest { ...@@ -132,10 +133,10 @@ public final class EndpointRequest {
} }
@Override @Override
protected void initialized(PathMappedEndpoints pathMappedEndpoints) { protected void initialized(Supplier<PathMappedEndpoints> pathMappedEndpoints) {
Set<String> paths = new LinkedHashSet<>(); Set<String> paths = new LinkedHashSet<>();
if (this.includes.isEmpty()) { if (this.includes.isEmpty()) {
paths.addAll(pathMappedEndpoints.getAllPaths()); paths.addAll(pathMappedEndpoints.get().getAllPaths());
} }
streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add); streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add);
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove); streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove);
...@@ -143,9 +144,9 @@ public final class EndpointRequest { ...@@ -143,9 +144,9 @@ public final class EndpointRequest {
} }
private Stream<String> streamPaths(List<Object> source, private Stream<String> streamPaths(List<Object> source,
PathMappedEndpoints pathMappedEndpoints) { Supplier<PathMappedEndpoints> pathMappedEndpoints) {
return source.stream().filter(Objects::nonNull).map(this::getEndpointId) return source.stream().filter(Objects::nonNull).map(this::getEndpointId)
.map(pathMappedEndpoints::getPath); .map(pathMappedEndpoints.get()::getPath);
} }
private String getEndpointId(Object source) { private String getEndpointId(Object source) {
...@@ -173,7 +174,7 @@ public final class EndpointRequest { ...@@ -173,7 +174,7 @@ public final class EndpointRequest {
@Override @Override
protected Mono<MatchResult> matches(ServerWebExchange exchange, protected Mono<MatchResult> matches(ServerWebExchange exchange,
PathMappedEndpoints context) { Supplier<PathMappedEndpoints> context) {
return this.delegate.matches(exchange); return this.delegate.matches(exchange);
} }
......
...@@ -23,6 +23,7 @@ import java.util.LinkedHashSet; ...@@ -23,6 +23,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -129,13 +130,13 @@ public final class EndpointRequest { ...@@ -129,13 +130,13 @@ public final class EndpointRequest {
} }
@Override @Override
protected void initialized(PathMappedEndpoints pathMappedEndpoints) { protected void initialized(Supplier<PathMappedEndpoints> pathMappedEndpoints) {
Set<String> paths = new LinkedHashSet<>(); Set<String> paths = new LinkedHashSet<>();
if (this.includes.isEmpty()) { if (this.includes.isEmpty()) {
paths.addAll(pathMappedEndpoints.getAllPaths()); paths.addAll(pathMappedEndpoints.get().getAllPaths());
} }
streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add); streamPaths(this.includes, pathMappedEndpoints.get()).forEach(paths::add);
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove); streamPaths(this.excludes, pathMappedEndpoints.get()).forEach(paths::remove);
this.delegate = new OrRequestMatcher(getDelegateMatchers(paths)); this.delegate = new OrRequestMatcher(getDelegateMatchers(paths));
} }
...@@ -169,7 +170,7 @@ public final class EndpointRequest { ...@@ -169,7 +170,7 @@ public final class EndpointRequest {
@Override @Override
protected boolean matches(HttpServletRequest request, protected boolean matches(HttpServletRequest request,
PathMappedEndpoints context) { Supplier<PathMappedEndpoints> context) {
return this.delegate.matches(request); return this.delegate.matches(request);
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.security.servlet; package org.springframework.boot.autoconfigure.security.servlet;
import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties; import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties;
...@@ -69,14 +71,14 @@ public final class PathRequest { ...@@ -69,14 +71,14 @@ public final class PathRequest {
} }
@Override @Override
protected void initialized(H2ConsoleProperties h2ConsoleProperties) { protected void initialized(Supplier<H2ConsoleProperties> h2ConsoleProperties) {
this.delegate = new AntPathRequestMatcher( this.delegate = new AntPathRequestMatcher(
h2ConsoleProperties.getPath() + "/**"); h2ConsoleProperties.get().getPath() + "/**");
} }
@Override @Override
protected boolean matches(HttpServletRequest request, protected boolean matches(HttpServletRequest request,
H2ConsoleProperties context) { Supplier<H2ConsoleProperties> context) {
return this.delegate.matches(request); return this.delegate.matches(request);
} }
......
...@@ -20,6 +20,7 @@ import java.util.EnumSet; ...@@ -20,6 +20,7 @@ import java.util.EnumSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -133,8 +134,9 @@ public final class StaticResourceRequest { ...@@ -133,8 +134,9 @@ public final class StaticResourceRequest {
} }
@Override @Override
protected void initialized(ServerProperties serverProperties) { protected void initialized(Supplier<ServerProperties> serverProperties) {
this.delegate = new OrRequestMatcher(getDelegateMatchers(serverProperties)); this.delegate = new OrRequestMatcher(
getDelegateMatchers(serverProperties.get()));
} }
private List<RequestMatcher> getDelegateMatchers( private List<RequestMatcher> getDelegateMatchers(
...@@ -149,7 +151,8 @@ public final class StaticResourceRequest { ...@@ -149,7 +151,8 @@ public final class StaticResourceRequest {
} }
@Override @Override
protected boolean matches(HttpServletRequest request, ServerProperties context) { protected boolean matches(HttpServletRequest request,
Supplier<ServerProperties> context) {
return this.delegate.matches(request); return this.delegate.matches(request);
} }
......
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
package org.springframework.boot.security.reactive; package org.springframework.boot.security.reactive;
import java.util.function.Supplier;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
...@@ -32,9 +33,8 @@ import org.springframework.web.server.ServerWebExchange; ...@@ -32,9 +33,8 @@ import org.springframework.web.server.ServerWebExchange;
* that is autowired in the usual way. * that is autowired in the usual way.
* *
* @param <C> The type of the context that the match method actually needs to use. Can be * @param <C> The type of the context that the match method actually needs to use. Can be
* an {@link ApplicationContext}, a class of an {@link ApplicationContext#getBean(Class) * an {@link ApplicationContext} or a class of an {@link ApplicationContext#getBean(Class)
* existing bean} or a custom type that will be * existing bean}.
* {@link AutowireCapableBeanFactory#createBean(Class, int, boolean) created} on demand.
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
*/ */
...@@ -43,7 +43,7 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C> ...@@ -43,7 +43,7 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C>
private final Class<? extends C> contextClass; private final Class<? extends C> contextClass;
private volatile C context; private volatile Supplier<C> context;
private final Object contextLock = new Object(); private final Object contextLock = new Object();
...@@ -60,12 +60,13 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C> ...@@ -60,12 +60,13 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C>
/** /**
* Decides whether the rule implemented by the strategy matches the supplied exchange. * Decides whether the rule implemented by the strategy matches the supplied exchange.
* @param exchange the source exchange * @param exchange the source exchange
* @param context the context instance * @param context a supplier for the initialized context (may throw an exception)
* @return if the exchange matches * @return if the exchange matches
*/ */
protected abstract Mono<MatchResult> matches(ServerWebExchange exchange, C context); protected abstract Mono<MatchResult> matches(ServerWebExchange exchange,
Supplier<C> context);
protected C getContext(ServerWebExchange exchange) { protected Supplier<C> getContext(ServerWebExchange exchange) {
if (this.context == null) { if (this.context == null) {
synchronized (this.contextLock) { synchronized (this.contextLock) {
if (this.context == null) { if (this.context == null) {
...@@ -79,26 +80,19 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C> ...@@ -79,26 +80,19 @@ public abstract class ApplicationContextServerWebExchangeMatcher<C>
/** /**
* Called once the context has been initialized. * Called once the context has been initialized.
* @param context the initialized context * @param context a supplier for the initialized context (may throw an exception)
*/ */
protected void initialized(C context) { protected void initialized(Supplier<C> context) {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private C createContext(ServerWebExchange exchange) { private Supplier<C> createContext(ServerWebExchange exchange) {
ApplicationContext context = exchange.getApplicationContext(); ApplicationContext context = exchange.getApplicationContext();
Assert.state(context != null, "No WebApplicationContext found."); Assert.state(context != null, "No WebApplicationContext found.");
if (this.contextClass.isInstance(context)) { if (this.contextClass.isInstance(context)) {
return (C) context; return () -> (C) context;
}
try {
return context.getBean(this.contextClass);
}
catch (NoSuchBeanDefinitionException ex) {
return (C) context.getAutowireCapableBeanFactory().createBean(
this.contextClass, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR,
false);
} }
return () -> context.getBean(this.contextClass);
} }
} }
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
package org.springframework.boot.security.servlet; package org.springframework.boot.security.servlet;
import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
...@@ -33,9 +34,8 @@ import org.springframework.web.context.support.WebApplicationContextUtils; ...@@ -33,9 +34,8 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
* that is autowired in the usual way. * that is autowired in the usual way.
* *
* @param <C> The type of the context that the match method actually needs to use. Can be * @param <C> The type of the context that the match method actually needs to use. Can be
* an {@link ApplicationContext}, a class of an {@link ApplicationContext#getBean(Class) * an {@link ApplicationContext} or a class of an {@link ApplicationContext#getBean(Class)
* existing bean} or a custom type that will be * existing bean}.
* {@link AutowireCapableBeanFactory#createBean(Class, int, boolean) created} on demand.
* @author Phillip Webb * @author Phillip Webb
* @since 2.0.0 * @since 2.0.0
*/ */
...@@ -43,7 +43,7 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc ...@@ -43,7 +43,7 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
private final Class<? extends C> contextClass; private final Class<? extends C> contextClass;
private volatile C context; private volatile Supplier<C> context;
private final Object contextLock = new Object(); private final Object contextLock = new Object();
...@@ -60,12 +60,12 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc ...@@ -60,12 +60,12 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
/** /**
* Decides whether the rule implemented by the strategy matches the supplied request. * Decides whether the rule implemented by the strategy matches the supplied request.
* @param request the source request * @param request the source request
* @param context the context instance * @param context a supplier for the initialized context (may throw an exception)
* @return if the request matches * @return if the request matches
*/ */
protected abstract boolean matches(HttpServletRequest request, C context); protected abstract boolean matches(HttpServletRequest request, Supplier<C> context);
private C getContext(HttpServletRequest request) { private Supplier<C> getContext(HttpServletRequest request) {
if (this.context == null) { if (this.context == null) {
synchronized (this.contextLock) { synchronized (this.contextLock) {
if (this.context == null) { if (this.context == null) {
...@@ -79,26 +79,19 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc ...@@ -79,26 +79,19 @@ public abstract class ApplicationContextRequestMatcher<C> implements RequestMatc
/** /**
* Called once the context has been initialized. * Called once the context has been initialized.
* @param context the initialized context * @param context a supplier for the initialized context (may throw an exception)
*/ */
protected void initialized(C context) { protected void initialized(Supplier<C> context) {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private C createContext(HttpServletRequest request) { private Supplier<C> createContext(HttpServletRequest request) {
WebApplicationContext context = WebApplicationContextUtils WebApplicationContext context = WebApplicationContextUtils
.getRequiredWebApplicationContext(request.getServletContext()); .getRequiredWebApplicationContext(request.getServletContext());
if (this.contextClass.isInstance(context)) { if (this.contextClass.isInstance(context)) {
return (C) context; return () -> (C) context;
}
try {
return context.getBean(this.contextClass);
}
catch (NoSuchBeanDefinitionException ex) {
return (C) context.getAutowireCapableBeanFactory().createBean(
this.contextClass, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR,
false);
} }
return () -> context.getBean(this.contextClass);
} }
} }
...@@ -16,11 +16,14 @@ ...@@ -16,11 +16,14 @@
package org.springframework.boot.security.reactive; package org.springframework.boot.security.reactive;
import java.util.function.Supplier;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.StaticApplicationContext; import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
...@@ -58,8 +61,8 @@ public class ApplicationContextServerWebExchangeMatcherTests { ...@@ -58,8 +61,8 @@ public class ApplicationContextServerWebExchangeMatcherTests {
StaticApplicationContext context = (StaticApplicationContext) exchange StaticApplicationContext context = (StaticApplicationContext) exchange
.getApplicationContext(); .getApplicationContext();
assertThat(new TestApplicationContextServerWebExchangeMatcher<>( assertThat(new TestApplicationContextServerWebExchangeMatcher<>(
ApplicationContext.class).callMatchesAndReturnProvidedContext(exchange)) ApplicationContext.class).callMatchesAndReturnProvidedContext(exchange)
.isEqualTo(context); .get()).isEqualTo(context);
} }
@Test @Test
...@@ -70,19 +73,17 @@ public class ApplicationContextServerWebExchangeMatcherTests { ...@@ -70,19 +73,17 @@ public class ApplicationContextServerWebExchangeMatcherTests {
context.registerSingleton("existingBean", ExistingBean.class); context.registerSingleton("existingBean", ExistingBean.class);
assertThat( assertThat(
new TestApplicationContextServerWebExchangeMatcher<>(ExistingBean.class) new TestApplicationContextServerWebExchangeMatcher<>(ExistingBean.class)
.callMatchesAndReturnProvidedContext(exchange)) .callMatchesAndReturnProvidedContext(exchange).get())
.isEqualTo(context.getBean(ExistingBean.class)); .isEqualTo(context.getBean(ExistingBean.class));
} }
@Test @Test
public void matchesWhenContextClassIsNewBeanShouldProvideBean() { public void matchesWhenContextClassIsMissingBeanShouldProvideException() {
ServerWebExchange exchange = createHttpWebHandlerAdapter(); ServerWebExchange exchange = createHttpWebHandlerAdapter();
StaticApplicationContext context = (StaticApplicationContext) exchange Supplier<ExistingBean> supplier = new TestApplicationContextServerWebExchangeMatcher<>(
.getApplicationContext(); ExistingBean.class).callMatchesAndReturnProvidedContext(exchange);
context.registerSingleton("existingBean", ExistingBean.class); this.thrown.expect(NoSuchBeanDefinitionException.class);
assertThat(new TestApplicationContextServerWebExchangeMatcher<>(NewBean.class) supplier.get();
.callMatchesAndReturnProvidedContext(exchange).getBean())
.isEqualTo(context.getBean(ExistingBean.class));
} }
@Test @Test
...@@ -139,24 +140,25 @@ public class ApplicationContextServerWebExchangeMatcherTests { ...@@ -139,24 +140,25 @@ public class ApplicationContextServerWebExchangeMatcherTests {
static class TestApplicationContextServerWebExchangeMatcher<C> static class TestApplicationContextServerWebExchangeMatcher<C>
extends ApplicationContextServerWebExchangeMatcher<C> { extends ApplicationContextServerWebExchangeMatcher<C> {
private C providedContext; private Supplier<C> providedContext;
TestApplicationContextServerWebExchangeMatcher(Class<? extends C> context) { TestApplicationContextServerWebExchangeMatcher(Class<? extends C> context) {
super(context); super(context);
} }
C callMatchesAndReturnProvidedContext(ServerWebExchange exchange) { Supplier<C> callMatchesAndReturnProvidedContext(ServerWebExchange exchange) {
matches(exchange); matches(exchange);
return getProvidedContext(); return getProvidedContext();
} }
@Override @Override
protected Mono<MatchResult> matches(ServerWebExchange exchange, C context) { protected Mono<MatchResult> matches(ServerWebExchange exchange,
Supplier<C> context) {
this.providedContext = context; this.providedContext = context;
return MatchResult.match(); return MatchResult.match();
} }
C getProvidedContext() { Supplier<C> getProvidedContext() {
return this.providedContext; return this.providedContext;
} }
......
...@@ -16,12 +16,15 @@ ...@@ -16,12 +16,15 @@
package org.springframework.boot.security.servlet; package org.springframework.boot.security.servlet;
import java.util.function.Supplier;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext; import org.springframework.mock.web.MockServletContext;
...@@ -51,7 +54,7 @@ public class ApplicationContextRequestMatcherTests { ...@@ -51,7 +54,7 @@ public class ApplicationContextRequestMatcherTests {
public void matchesWhenContextClassIsApplicationContextShouldProvideContext() { public void matchesWhenContextClassIsApplicationContextShouldProvideContext() {
StaticWebApplicationContext context = createWebApplicationContext(); StaticWebApplicationContext context = createWebApplicationContext();
assertThat(new TestApplicationContextRequestMatcher<>(ApplicationContext.class) assertThat(new TestApplicationContextRequestMatcher<>(ApplicationContext.class)
.callMatchesAndReturnProvidedContext(context)).isEqualTo(context); .callMatchesAndReturnProvidedContext(context).get()).isEqualTo(context);
} }
@Test @Test
...@@ -59,17 +62,17 @@ public class ApplicationContextRequestMatcherTests { ...@@ -59,17 +62,17 @@ public class ApplicationContextRequestMatcherTests {
StaticWebApplicationContext context = createWebApplicationContext(); StaticWebApplicationContext context = createWebApplicationContext();
context.registerSingleton("existingBean", ExistingBean.class); context.registerSingleton("existingBean", ExistingBean.class);
assertThat(new TestApplicationContextRequestMatcher<>(ExistingBean.class) assertThat(new TestApplicationContextRequestMatcher<>(ExistingBean.class)
.callMatchesAndReturnProvidedContext(context)) .callMatchesAndReturnProvidedContext(context).get())
.isEqualTo(context.getBean(ExistingBean.class)); .isEqualTo(context.getBean(ExistingBean.class));
} }
@Test @Test
public void matchesWhenContextClassIsNewBeanShouldProvideBean() { public void matchesWhenContextClassIsBeanThatDoesntExistShouldSupplyException() {
StaticWebApplicationContext context = createWebApplicationContext(); StaticWebApplicationContext context = createWebApplicationContext();
context.registerSingleton("existingBean", ExistingBean.class); Supplier<ExistingBean> supplier = new TestApplicationContextRequestMatcher<>(
assertThat(new TestApplicationContextRequestMatcher<>(NewBean.class) ExistingBean.class).callMatchesAndReturnProvidedContext(context);
.callMatchesAndReturnProvidedContext(context).getBean()) this.thrown.expect(NoSuchBeanDefinitionException.class);
.isEqualTo(context.getBean(ExistingBean.class)); supplier.get();
} }
private StaticWebApplicationContext createWebApplicationContext() { private StaticWebApplicationContext createWebApplicationContext() {
...@@ -102,29 +105,31 @@ public class ApplicationContextRequestMatcherTests { ...@@ -102,29 +105,31 @@ public class ApplicationContextRequestMatcherTests {
static class TestApplicationContextRequestMatcher<C> static class TestApplicationContextRequestMatcher<C>
extends ApplicationContextRequestMatcher<C> { extends ApplicationContextRequestMatcher<C> {
private C providedContext; private Supplier<C> providedContext;
TestApplicationContextRequestMatcher(Class<? extends C> context) { TestApplicationContextRequestMatcher(Class<? extends C> context) {
super(context); super(context);
} }
public C callMatchesAndReturnProvidedContext(WebApplicationContext context) { public Supplier<C> callMatchesAndReturnProvidedContext(
WebApplicationContext context) {
return callMatchesAndReturnProvidedContext( return callMatchesAndReturnProvidedContext(
new MockHttpServletRequest(context.getServletContext())); new MockHttpServletRequest(context.getServletContext()));
} }
public C callMatchesAndReturnProvidedContext(HttpServletRequest request) { public Supplier<C> callMatchesAndReturnProvidedContext(
HttpServletRequest request) {
matches(request); matches(request);
return getProvidedContext(); return getProvidedContext();
} }
@Override @Override
protected boolean matches(HttpServletRequest request, C context) { protected boolean matches(HttpServletRequest request, Supplier<C> context) {
this.providedContext = context; this.providedContext = context;
return false; return false;
} }
public C getProvidedContext() { public Supplier<C> getProvidedContext() {
return this.providedContext; return this.providedContext;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment