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
This commit is contained in:
parent
802cd856aa
commit
d66496787d
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
@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;
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
|
|
||||||
@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 @@
|
||||||
|
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 @@
|
||||||
|
|
||||||
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;
|
||||||
* 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>
|
||||||
|
|
||||||
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>
|
||||||
/**
|
/**
|
||||||
* 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>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 @@
|
||||||
|
|
||||||
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;
|
||||||
* 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
|
||||||
|
|
||||||
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
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 @@
|
||||||
|
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 @@
|
||||||
|
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue