Commit a4b0be08 authored by Phillip Webb's avatar Phillip Webb

Polish

parent 220f8cdc
...@@ -59,11 +59,11 @@ public final class EndpointRequest { ...@@ -59,11 +59,11 @@ public final class EndpointRequest {
} }
/** /**
* Returns a matcher that includes all {@link Endpoint actuator endpoints}. It also includes * Returns a matcher that includes all {@link Endpoint actuator endpoints}. It also
* the links endpoint which is present at the base path of the actuator endpoints. The * includes the links endpoint which is present at the base path of the actuator
* {@link EndpointServerWebExchangeMatcher#excluding(Class...) excluding} method can * endpoints. The {@link EndpointServerWebExchangeMatcher#excluding(Class...)
* be used to further remove specific endpoints if required. For example: * excluding} method can be used to further remove specific endpoints if required. For
* <pre class="code"> * example: <pre class="code">
* EndpointRequest.toAnyEndpoint().excluding(ShutdownEndpoint.class) * EndpointRequest.toAnyEndpoint().excluding(ShutdownEndpoint.class)
* </pre> * </pre>
* @return the configured {@link ServerWebExchangeMatcher} * @return the configured {@link ServerWebExchangeMatcher}
...@@ -97,11 +97,13 @@ public final class EndpointRequest { ...@@ -97,11 +97,13 @@ public final class EndpointRequest {
} }
/** /**
* Returns a matcher that matches only on the links endpoint. It can be used when security configuration * Returns a matcher that matches only on the links endpoint. It can be used when
* for the links endpoint is different from the other {@link Endpoint actuator endpoints}. The * security configuration for the links endpoint is different from the other
* {@link EndpointServerWebExchangeMatcher#excludingLinks() excludingLinks} method can be used in combination with this * {@link Endpoint actuator endpoints}. The
* to remove the links endpoint from {@link EndpointRequest#toAnyEndpoint() toAnyEndpoint}. * {@link EndpointServerWebExchangeMatcher#excludingLinks() excludingLinks} method can
* For example: <pre class="code"> * be used in combination with this to remove the links endpoint from
* {@link EndpointRequest#toAnyEndpoint() toAnyEndpoint}. For example:
* <pre class="code">
* EndpointRequest.toLinks() * EndpointRequest.toLinks()
* </pre> * </pre>
* @return the configured {@link ServerWebExchangeMatcher} * @return the configured {@link ServerWebExchangeMatcher}
...@@ -121,20 +123,24 @@ public final class EndpointRequest { ...@@ -121,20 +123,24 @@ public final class EndpointRequest {
private final List<Object> excludes; private final List<Object> excludes;
private ServerWebExchangeMatcher delegate; private final boolean includeLinks;
private boolean includeLinks; private ServerWebExchangeMatcher delegate;
private EndpointServerWebExchangeMatcher(boolean includeLinks) { private EndpointServerWebExchangeMatcher(boolean includeLinks) {
this(Collections.emptyList(), Collections.emptyList(), includeLinks); this(Collections.emptyList(), Collections.emptyList(), includeLinks);
} }
private EndpointServerWebExchangeMatcher(Class<?>[] endpoints, boolean includeLinks) { private EndpointServerWebExchangeMatcher(Class<?>[] endpoints,
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(), includeLinks); boolean includeLinks) {
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(),
includeLinks);
} }
private EndpointServerWebExchangeMatcher(String[] endpoints, boolean includeLinks) { private EndpointServerWebExchangeMatcher(String[] endpoints,
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(), includeLinks); boolean includeLinks) {
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(),
includeLinks);
} }
private EndpointServerWebExchangeMatcher(List<Object> includes, private EndpointServerWebExchangeMatcher(List<Object> includes,
...@@ -148,17 +154,20 @@ public final class EndpointRequest { ...@@ -148,17 +154,20 @@ public final class EndpointRequest {
public EndpointServerWebExchangeMatcher excluding(Class<?>... endpoints) { public EndpointServerWebExchangeMatcher excluding(Class<?>... endpoints) {
List<Object> excludes = new ArrayList<>(this.excludes); List<Object> excludes = new ArrayList<>(this.excludes);
excludes.addAll(Arrays.asList((Object[]) endpoints)); excludes.addAll(Arrays.asList((Object[]) endpoints));
return new EndpointServerWebExchangeMatcher(this.includes, excludes, this.includeLinks); return new EndpointServerWebExchangeMatcher(this.includes, excludes,
this.includeLinks);
} }
public EndpointServerWebExchangeMatcher excluding(String... endpoints) { public EndpointServerWebExchangeMatcher excluding(String... endpoints) {
List<Object> excludes = new ArrayList<>(this.excludes); List<Object> excludes = new ArrayList<>(this.excludes);
excludes.addAll(Arrays.asList((Object[]) endpoints)); excludes.addAll(Arrays.asList((Object[]) endpoints));
return new EndpointServerWebExchangeMatcher(this.includes, excludes, this.includeLinks); return new EndpointServerWebExchangeMatcher(this.includes, excludes,
this.includeLinks);
} }
public EndpointServerWebExchangeMatcher excludingLinks() { public EndpointServerWebExchangeMatcher excludingLinks() {
return new EndpointServerWebExchangeMatcher(this.includes, this.excludes, false); return new EndpointServerWebExchangeMatcher(this.includes, this.excludes,
false);
} }
@Override @Override
...@@ -185,8 +194,10 @@ public final class EndpointRequest { ...@@ -185,8 +194,10 @@ public final class EndpointRequest {
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);
List<ServerWebExchangeMatcher> delegateMatchers = getDelegateMatchers(paths); List<ServerWebExchangeMatcher> delegateMatchers = getDelegateMatchers(paths);
if (this.includeLinks && StringUtils.hasText(pathMappedEndpoints.getBasePath())) { if (this.includeLinks
delegateMatchers.add(new PathPatternParserServerWebExchangeMatcher(pathMappedEndpoints.getBasePath())); && StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
delegateMatchers.add(new PathPatternParserServerWebExchangeMatcher(
pathMappedEndpoints.getBasePath()));
} }
return new OrServerWebExchangeMatcher(delegateMatchers); return new OrServerWebExchangeMatcher(delegateMatchers);
} }
...@@ -241,15 +252,17 @@ public final class EndpointRequest { ...@@ -241,15 +252,17 @@ public final class EndpointRequest {
} }
@Override @Override
protected void initialized(Supplier<WebEndpointProperties> propertiesSupplier) { protected void initialized(Supplier<WebEndpointProperties> properties) {
WebEndpointProperties webEndpointProperties = propertiesSupplier.get(); this.delegate = createDelegate(properties.get());
if (StringUtils.hasText(webEndpointProperties.getBasePath())) { }
this.delegate = new PathPatternParserServerWebExchangeMatcher(
webEndpointProperties.getBasePath()); private ServerWebExchangeMatcher createDelegate(
} WebEndpointProperties properties) {
else { if (StringUtils.hasText(properties.getBasePath())) {
this.delegate = EMPTY_MATCHER; return new PathPatternParserServerWebExchangeMatcher(
properties.getBasePath());
} }
return EMPTY_MATCHER;
} }
@Override @Override
......
...@@ -57,10 +57,11 @@ public final class EndpointRequest { ...@@ -57,10 +57,11 @@ public final class EndpointRequest {
} }
/** /**
* Returns a matcher that includes all {@link Endpoint actuator endpoints}. It also includes * Returns a matcher that includes all {@link Endpoint actuator endpoints}. It also
* the links endpoint which is present at the base path of the actuator endpoints. The * includes the links endpoint which is present at the base path of the actuator
* {@link EndpointRequestMatcher#excluding(Class...) excluding} method can be used to * endpoints. The {@link EndpointRequestMatcher#excluding(Class...) excluding} method
* further remove specific endpoints if required. For example: <pre class="code"> * can be used to further remove specific endpoints if required. For example:
* <pre class="code">
* EndpointRequest.toAnyEndpoint().excluding(ShutdownEndpoint.class) * EndpointRequest.toAnyEndpoint().excluding(ShutdownEndpoint.class)
* </pre> * </pre>
* @return the configured {@link RequestMatcher} * @return the configured {@link RequestMatcher}
...@@ -94,11 +95,13 @@ public final class EndpointRequest { ...@@ -94,11 +95,13 @@ public final class EndpointRequest {
} }
/** /**
* Returns a matcher that matches only on the links endpoint. It can be used when security configuration * Returns a matcher that matches only on the links endpoint. It can be used when
* for the links endpoint is different from the other {@link Endpoint actuator endpoints}. The * security configuration for the links endpoint is different from the other
* {@link EndpointRequestMatcher#excludingLinks() excludingLinks} method can be used in combination with this * {@link Endpoint actuator endpoints}. The
* to remove the links endpoint from {@link EndpointRequest#toAnyEndpoint() toAnyEndpoint}. * {@link EndpointRequestMatcher#excludingLinks() excludingLinks} method can be used
* For example: <pre class="code"> * in combination with this to remove the links endpoint from
* {@link EndpointRequest#toAnyEndpoint() toAnyEndpoint}. For example:
* <pre class="code">
* EndpointRequest.toLinks() * EndpointRequest.toLinks()
* </pre> * </pre>
* @return the configured {@link RequestMatcher} * @return the configured {@link RequestMatcher}
...@@ -126,14 +129,17 @@ public final class EndpointRequest { ...@@ -126,14 +129,17 @@ public final class EndpointRequest {
} }
private EndpointRequestMatcher(Class<?>[] endpoints, boolean includeLinks) { private EndpointRequestMatcher(Class<?>[] endpoints, boolean includeLinks) {
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(), includeLinks); this(Arrays.asList((Object[]) endpoints), Collections.emptyList(),
includeLinks);
} }
private EndpointRequestMatcher(String[] endpoints, boolean includeLinks) { private EndpointRequestMatcher(String[] endpoints, boolean includeLinks) {
this(Arrays.asList((Object[]) endpoints), Collections.emptyList(), includeLinks); this(Arrays.asList((Object[]) endpoints), Collections.emptyList(),
includeLinks);
} }
private EndpointRequestMatcher(List<Object> includes, List<Object> excludes, boolean includeLinks) { private EndpointRequestMatcher(List<Object> includes, List<Object> excludes,
boolean includeLinks) {
super(PathMappedEndpoints.class); super(PathMappedEndpoints.class);
this.includes = includes; this.includes = includes;
this.excludes = excludes; this.excludes = excludes;
...@@ -179,8 +185,10 @@ public final class EndpointRequest { ...@@ -179,8 +185,10 @@ public final class EndpointRequest {
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);
List<RequestMatcher> delegateMatchers = getDelegateMatchers(paths); List<RequestMatcher> delegateMatchers = getDelegateMatchers(paths);
if (this.includeLinks && StringUtils.hasText(pathMappedEndpoints.getBasePath())) { if (this.includeLinks
delegateMatchers.add(new AntPathRequestMatcher(pathMappedEndpoints.getBasePath())); && StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
delegateMatchers.add(
new AntPathRequestMatcher(pathMappedEndpoints.getBasePath()));
} }
return new OrRequestMatcher(delegateMatchers); return new OrRequestMatcher(delegateMatchers);
} }
...@@ -234,20 +242,23 @@ public final class EndpointRequest { ...@@ -234,20 +242,23 @@ public final class EndpointRequest {
} }
@Override @Override
protected void initialized(Supplier<WebEndpointProperties> propertiesSupplier) { protected void initialized(Supplier<WebEndpointProperties> properties) {
WebEndpointProperties webEndpointProperties = propertiesSupplier.get(); this.delegate = createDelegate(properties.get());
if (StringUtils.hasText(webEndpointProperties.getBasePath())) { }
this.delegate = new AntPathRequestMatcher(webEndpointProperties.getBasePath());
} private RequestMatcher createDelegate(WebEndpointProperties properties) {
else { if (StringUtils.hasText(properties.getBasePath())) {
this.delegate = EMPTY_MATCHER; return new AntPathRequestMatcher(properties.getBasePath());
} }
return EMPTY_MATCHER;
} }
@Override @Override
protected boolean matches(HttpServletRequest request, Supplier<WebEndpointProperties> context) { protected boolean matches(HttpServletRequest request,
Supplier<WebEndpointProperties> context) {
return this.delegate.matches(request); return this.delegate.matches(request);
} }
} }
} }
...@@ -78,14 +78,16 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests { ...@@ -78,14 +78,16 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(
ReactiveSecurityAutoConfiguration.class,
ReactiveUserDetailsServiceAutoConfiguration.class, ReactiveUserDetailsServiceAutoConfiguration.class,
WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class, WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
WebClientCustomizerConfig.class, WebClientAutoConfiguration.class, WebClientCustomizerConfig.class, WebClientAutoConfiguration.class,
ManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
WebEndpointAutoConfiguration.class, HealthEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
ReactiveCloudFoundryActuatorAutoConfiguration.class)); ReactiveCloudFoundryActuatorAutoConfiguration.class));
@After @After
...@@ -96,137 +98,153 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests { ...@@ -96,137 +98,153 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformActive() { public void cloudFoundryPlatformActive() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils context);
.getField(handlerMapping, "endpointMapping"); EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication"); .getField(handlerMapping, "endpointMapping");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils assertThat(endpointMapping.getPath())
.getField(handlerMapping, "corsConfiguration"); .isEqualTo("/cloudfoundryapplication");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
assertThat(corsConfiguration.getAllowedMethods()).containsAll( .getField(handlerMapping, "corsConfiguration");
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name())); assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
assertThat(corsConfiguration.getAllowedHeaders()).containsAll( assertThat(corsConfiguration.getAllowedMethods()).containsAll(
Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type")); Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
}); assertThat(corsConfiguration.getAllowedHeaders())
.containsAll(Arrays.asList("Authorization",
"X-Cf-App-Instance", "Content-Type"));
});
} }
@Test @Test
public void cloudfoundryapplicationProducesActuatorMediaType() { public void cloudfoundryapplicationProducesActuatorMediaType() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context) WebTestClient webTestClient = WebTestClient
.build(); .bindToApplicationContext(context).build();
webTestClient.get().uri("/cloudfoundryapplication").header("Content-Type", webTestClient.get().uri("/cloudfoundryapplication").header(
ActuatorMediaType.V2_JSON + ";charset=UTF-8"); "Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8");
}); });
} }
@Test @Test
public void cloudFoundryPlatformActiveSetsApplicationId() { public void cloudFoundryPlatformActiveSetsApplicationId() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
Object interceptor = ReflectionTestUtils.getField(handlerMapping, context);
"securityInterceptor"); Object interceptor = ReflectionTestUtils.getField(handlerMapping,
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "securityInterceptor");
"applicationId"); String applicationId = (String) ReflectionTestUtils
assertThat(applicationId).isEqualTo("my-app-id"); .getField(interceptor, "applicationId");
}); assertThat(applicationId).isEqualTo("my-app-id");
});
} }
@Test @Test
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() { public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
Object interceptor = ReflectionTestUtils.getField(handlerMapping, context);
"securityInterceptor"); Object interceptor = ReflectionTestUtils.getField(handlerMapping,
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, "securityInterceptor");
"cloudFoundrySecurityService"); Object interceptorSecurityService = ReflectionTestUtils
String cloudControllerUrl = (String) ReflectionTestUtils .getField(interceptor, "cloudFoundrySecurityService");
.getField(interceptorSecurityService, "cloudControllerUrl"); String cloudControllerUrl = (String) ReflectionTestUtils
assertThat(cloudControllerUrl).isEqualTo("http://my-cloud-controller.com"); .getField(interceptorSecurityService, "cloudControllerUrl");
}); assertThat(cloudControllerUrl)
.isEqualTo("http://my-cloud-controller.com");
});
} }
@Test @Test
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() { public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
this.contextRunner this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") "vcap.application.application_id:my-app-id").run((context) -> {
.run(context -> { CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean( .getBean("cloudFoundryWebFluxEndpointHandlerMapping",
"cloudFoundryWebFluxEndpointHandlerMapping", CloudFoundryWebFluxEndpointHandlerMapping.class);
CloudFoundryWebFluxEndpointHandlerMapping.class); Object securityInterceptor = ReflectionTestUtils
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, .getField(handlerMapping, "securityInterceptor");
"securityInterceptor"); Object interceptorSecurityService = ReflectionTestUtils
Object interceptorSecurityService = ReflectionTestUtils .getField(securityInterceptor, "cloudFoundrySecurityService");
.getField(securityInterceptor, "cloudFoundrySecurityService"); assertThat(interceptorSecurityService).isNull();
assertThat(interceptorSecurityService).isNull(); });
});
} }
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void cloudFoundryPathsIgnoredBySpringSecurity() { public void cloudFoundryPathsIgnoredBySpringSecurity() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class); WebFilterChainProxy chainProxy = context
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils .getBean(WebFilterChainProxy.class);
.getField(chainProxy, "filters"); List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
Boolean cfRequestMatches = filters.get(0).matches(MockServerWebExchange.from( .getField(chainProxy, "filters");
MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build())) Boolean cfRequestMatches = filters.get(0)
.block(); .matches(MockServerWebExchange.from(MockServerHttpRequest
Boolean otherRequestMatches = filters.get(0) .get("/cloudfoundryapplication/my-path").build()))
.matches(MockServerWebExchange .block();
Boolean otherRequestMatches = filters.get(0)
.matches(MockServerWebExchange.from(MockServerHttpRequest
.get("/some-other-path").build()))
.block();
assertThat(cfRequestMatches).isTrue();
assertThat(otherRequestMatches).isFalse();
otherRequestMatches = filters.get(1).matches(MockServerWebExchange
.from(MockServerHttpRequest.get("/some-other-path").build())) .from(MockServerHttpRequest.get("/some-other-path").build()))
.block(); .block();
assertThat(cfRequestMatches).isTrue(); assertThat(otherRequestMatches).isTrue();
assertThat(otherRequestMatches).isFalse(); });
otherRequestMatches = filters.get(1)
.matches(MockServerWebExchange
.from(MockServerHttpRequest.get("/some-other-path").build()))
.block();
assertThat(otherRequestMatches).isTrue();
});
} }
@Test @Test
public void cloudFoundryPlatformInactive() { public void cloudFoundryPlatformInactive() {
this.contextRunner this.contextRunner.run((context) -> assertThat(
.run(context -> assertThat( context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
.isFalse()); .isFalse());
} }
@Test @Test
public void cloudFoundryManagementEndpointsDisabled() { public void cloudFoundryManagementEndpointsDisabled() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false") this.contextRunner
.run(context -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")) .withPropertyValues("VCAP_APPLICATION=---",
.isFalse()); "management.cloudfoundry.enabled:false")
.run((context) -> assertThat(
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
.isFalse());
} }
@Test @Test
public void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWebIncludes() { public void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWebIncludes() {
this.contextRunner.withUserConfiguration(TestConfiguration.class) this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints(); context);
List<String> endpointIds = endpoints.stream().map(ExposableEndpoint::getId) Collection<ExposableWebEndpoint> endpoints = handlerMapping
.collect(Collectors.toList()); .getEndpoints();
List<String> endpointIds = endpoints.stream()
.map(ExposableEndpoint::getId).collect(Collectors.toList());
assertThat(endpointIds).contains("test"); assertThat(endpointIds).contains("test");
}); });
} }
...@@ -234,72 +252,94 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests { ...@@ -234,72 +252,94 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void endpointPathCustomizationIsNotApplied() { public void endpointPathCustomizationIsNotApplied() {
this.contextRunner.withUserConfiguration(TestConfiguration.class) this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints(); context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
ExposableWebEndpoint endpoint = endpoints.stream() ExposableWebEndpoint endpoint = endpoints.stream()
.filter((candidate) -> "test".equals(candidate.getId())).findFirst() .filter((candidate) -> "test".equals(candidate.getId()))
.get(); .findFirst().get();
assertThat(endpoint.getOperations()).hasSize(1); assertThat(endpoint.getOperations()).hasSize(1);
WebOperation operation = endpoint.getOperations().iterator().next(); WebOperation operation = endpoint.getOperations().iterator().next();
assertThat(operation.getRequestPredicate().getPath()).isEqualTo("test"); assertThat(operation.getRequestPredicate().getPath())
.isEqualTo("test");
}); });
} }
@Test @Test
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() { public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(context).getEndpoints(); Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(
context).getEndpoints();
ExposableWebEndpoint endpoint = endpoints.iterator().next(); ExposableWebEndpoint endpoint = endpoints.iterator().next();
WebOperation webOperation = endpoint.getOperations().iterator().next(); WebOperation webOperation = endpoint.getOperations().iterator()
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker"); .next();
Object invoker = ReflectionTestUtils.getField(webOperation,
"invoker");
assertThat(ReflectionTestUtils.getField(invoker, "target")) assertThat(ReflectionTestUtils.getField(invoker, "target"))
.isInstanceOf(CloudFoundryReactiveHealthEndpointWebExtension.class); .isInstanceOf(
CloudFoundryReactiveHealthEndpointWebExtension.class);
}); });
} }
@Test @Test
public void skipSslValidation() { public void skipSslValidation() {
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com", "vcap.application.cf_api:http://my-cloud-controller.com",
"management.cloudfoundry.skip-ssl-validation:true") "management.cloudfoundry.skip-ssl-validation:true")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, Object interceptorSecurityService = ReflectionTestUtils
"cloudFoundrySecurityService"); .getField(interceptor, "cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils WebClient webClient = (WebClient) ReflectionTestUtils
.getField(interceptorSecurityService, "webClient"); .getField(interceptorSecurityService, "webClient");
webClient.get().uri("https://self-signed.badssl.com/").exchange().block(); webClient.get().uri("https://self-signed.badssl.com/").exchange()
.block();
}); });
} }
@Test @Test
public void sslValidationNotSkippedByDefault() { public void sslValidationNotSkippedByDefault() {
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, Object interceptorSecurityService = ReflectionTestUtils
"cloudFoundrySecurityService"); .getField(interceptor, "cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils WebClient webClient = (WebClient) ReflectionTestUtils
.getField(interceptorSecurityService, "webClient"); .getField(interceptorSecurityService, "webClient");
this.thrown.expectCause(instanceOf(SSLException.class)); this.thrown.expectCause(instanceOf(SSLException.class));
webClient.get().uri("https://self-signed.badssl.com/").exchange().block(); webClient.get().uri("https://self-signed.badssl.com/").exchange()
.block();
}); });
} }
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) { private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(
ApplicationContext context) {
return context.getBean("cloudFoundryWebFluxEndpointHandlerMapping", return context.getBean("cloudFoundryWebFluxEndpointHandlerMapping",
CloudFoundryWebFluxEndpointHandlerMapping.class); CloudFoundryWebFluxEndpointHandlerMapping.class);
} }
......
...@@ -81,46 +81,54 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -81,46 +81,54 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformActive() { public void cloudFoundryPlatformActive() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils context);
.getField(handlerMapping, "endpointMapping"); EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication"); .getField(handlerMapping, "endpointMapping");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils assertThat(endpointMapping.getPath())
.getField(handlerMapping, "corsConfiguration"); .isEqualTo("/cloudfoundryapplication");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
assertThat(corsConfiguration.getAllowedMethods()).containsAll( .getField(handlerMapping, "corsConfiguration");
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name())); assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
assertThat(corsConfiguration.getAllowedHeaders()).containsAll( assertThat(corsConfiguration.getAllowedMethods()).containsAll(
Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type")); Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
}); assertThat(corsConfiguration.getAllowedHeaders())
.containsAll(Arrays.asList("Authorization",
"X-Cf-App-Instance", "Content-Type"));
});
} }
@Test @Test
public void cloudfoundryapplicationProducesActuatorMediaType() throws Exception { public void cloudfoundryapplicationProducesActuatorMediaType() throws Exception {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
mockMvc.perform(get("/cloudfoundryapplication")).andExpect(header() mockMvc.perform(get("/cloudfoundryapplication"))
.string("Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8")); .andExpect(header().string("Content-Type",
}); ActuatorMediaType.V2_JSON + ";charset=UTF-8"));
});
} }
@Test @Test
public void cloudFoundryPlatformActiveSetsApplicationId() { public void cloudFoundryPlatformActiveSetsApplicationId() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
String applicationId = (String) ReflectionTestUtils.getField(interceptor, String applicationId = (String) ReflectionTestUtils
"applicationId"); .getField(interceptor, "applicationId");
assertThat(applicationId).isEqualTo("my-app-id"); assertThat(applicationId).isEqualTo("my-app-id");
}); });
} }
...@@ -128,31 +136,37 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -128,31 +136,37 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() { public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, Object interceptorSecurityService = ReflectionTestUtils
"cloudFoundrySecurityService"); .getField(interceptor, "cloudFoundrySecurityService");
String cloudControllerUrl = (String) ReflectionTestUtils String cloudControllerUrl = (String) ReflectionTestUtils
.getField(interceptorSecurityService, "cloudControllerUrl"); .getField(interceptorSecurityService, "cloudControllerUrl");
assertThat(cloudControllerUrl).isEqualTo("http://my-cloud-controller.com"); assertThat(cloudControllerUrl)
.isEqualTo("http://my-cloud-controller.com");
}); });
} }
@Test @Test
public void skipSslValidation() { public void skipSslValidation() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.cf_api:http://my-cloud-controller.com", "management.cloudfoundry.skip-ssl-validation:true") "vcap.application.application_id:my-app-id",
.run(context -> { "vcap.application.cf_api:http://my-cloud-controller.com",
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); "management.cloudfoundry.skip-ssl-validation:true")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, Object interceptorSecurityService = ReflectionTestUtils
"cloudFoundrySecurityService"); .getField(interceptor, "cloudFoundrySecurityService");
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
.getField(interceptorSecurityService, "restTemplate"); .getField(interceptorSecurityService, "restTemplate");
assertThat(restTemplate.getRequestFactory()) assertThat(restTemplate.getRequestFactory())
...@@ -162,12 +176,12 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -162,12 +176,12 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() { public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
this.contextRunner this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") "vcap.application.application_id:my-app-id").run((context) -> {
.run(context -> { CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); context);
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, Object securityInterceptor = ReflectionTestUtils
"securityInterceptor"); .getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils Object interceptorSecurityService = ReflectionTestUtils
.getField(securityInterceptor, "cloudFoundrySecurityService"); .getField(securityInterceptor, "cloudFoundrySecurityService");
assertThat(interceptorSecurityService).isNull(); assertThat(interceptorSecurityService).isNull();
...@@ -176,11 +190,12 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -176,11 +190,12 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPathsIgnoredBySpringSecurity() { public void cloudFoundryPathsIgnoredBySpringSecurity() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
.run(context -> { "vcap.application.application_id:my-app-id").run((context) -> {
FilterChainProxy securityFilterChain = (FilterChainProxy) context FilterChainProxy securityFilterChain = (FilterChainProxy) context
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN); .getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0); SecurityFilterChain chain = securityFilterChain.getFilterChains()
.get(0);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/cloudfoundryapplication/my-path"); request.setServletPath("/cloudfoundryapplication/my-path");
assertThat(chain.getFilters()).isEmpty(); assertThat(chain.getFilters()).isEmpty();
...@@ -193,73 +208,86 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -193,73 +208,86 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformInactive() { public void cloudFoundryPlatformInactive() {
this.contextRunner.withPropertyValues() this.contextRunner.withPropertyValues()
.run(context -> assertThat( .run((context) -> assertThat(context
context.containsBean("cloudFoundryWebEndpointServletHandlerMapping")) .containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse()); .isFalse());
} }
@Test @Test
public void cloudFoundryManagementEndpointsDisabled() { public void cloudFoundryManagementEndpointsDisabled() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false") this.contextRunner
.run(context -> assertThat(context.containsBean("cloudFoundryEndpointHandlerMapping")) .withPropertyValues("VCAP_APPLICATION=---",
.isFalse()); "management.cloudfoundry.enabled:false")
.run((context) -> assertThat(
context.containsBean("cloudFoundryEndpointHandlerMapping"))
.isFalse());
} }
@Test @Test
public void allEndpointsAvailableUnderCloudFoundryWithoutExposeAllOnWeb() { public void allEndpointsAvailableUnderCloudFoundryWithoutExposeAllOnWeb() {
this.contextRunner this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withUserConfiguration(TestConfiguration.class) .withPropertyValues("VCAP_APPLICATION:---",
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com") "vcap.application.cf_api:http://my-cloud-controller.com")
.run(context -> { .run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints(); context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
assertThat(endpoints.stream() assertThat(endpoints.stream()
.filter((candidate) -> "test".equals(candidate.getId())).findFirst()) .filter((candidate) -> "test".equals(candidate.getId()))
.isNotEmpty(); .findFirst()).isNotEmpty();
}); });
} }
@Test @Test
public void endpointPathCustomizationIsNotApplied() { public void endpointPathCustomizationIsNotApplied() {
this.contextRunner this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:http://my-cloud-controller.com", "vcap.application.cf_api:http://my-cloud-controller.com",
"management.endpoints.web.path-mapping.test=custom") "management.endpoints.web.path-mapping.test=custom")
.withUserConfiguration(TestConfiguration.class) .withUserConfiguration(TestConfiguration.class).run((context) -> {
.run(context -> { CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context); context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints(); Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
ExposableWebEndpoint endpoint = endpoints.stream() ExposableWebEndpoint endpoint = endpoints.stream()
.filter((candidate) -> "test".equals(candidate.getId())).findFirst() .filter((candidate) -> "test".equals(candidate.getId()))
.get(); .findFirst().get();
Collection<WebOperation> operations = endpoint.getOperations(); Collection<WebOperation> operations = endpoint.getOperations();
assertThat(operations).hasSize(1); assertThat(operations).hasSize(1);
assertThat(operations.iterator().next().getRequestPredicate().getPath()) assertThat(
.isEqualTo("test"); operations.iterator().next().getRequestPredicate().getPath())
.isEqualTo("test");
}); });
} }
@Test @Test
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() { public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", this.contextRunner
"vcap.application.cf_api:http://my-cloud-controller.com") .withPropertyValues("VCAP_APPLICATION:---",
.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) "vcap.application.application_id:my-app-id",
.run(context -> { "vcap.application.cf_api:http://my-cloud-controller.com")
.withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.run((context) -> {
Collection<ExposableWebEndpoint> endpoints = context Collection<ExposableWebEndpoint> endpoints = context
.getBean("cloudFoundryWebEndpointServletHandlerMapping", .getBean("cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class) CloudFoundryWebEndpointServletHandlerMapping.class)
.getEndpoints(); .getEndpoints();
ExposableWebEndpoint endpoint = endpoints.iterator().next(); ExposableWebEndpoint endpoint = endpoints.iterator().next();
WebOperation webOperation = endpoint.getOperations().iterator().next(); WebOperation webOperation = endpoint.getOperations().iterator()
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker"); .next();
Object invoker = ReflectionTestUtils.getField(webOperation,
"invoker");
assertThat(ReflectionTestUtils.getField(invoker, "target")) assertThat(ReflectionTestUtils.getField(invoker, "target"))
.isInstanceOf(CloudFoundryHealthEndpointWebExtension.class); .isInstanceOf(CloudFoundryHealthEndpointWebExtension.class);
}); });
} }
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(ApplicationContext context) { private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(
ApplicationContext context) {
return context.getBean("cloudFoundryWebEndpointServletHandlerMapping", return context.getBean("cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class); CloudFoundryWebEndpointServletHandlerMapping.class);
} }
......
...@@ -150,7 +150,8 @@ public class EndpointRequestTests { ...@@ -150,7 +150,8 @@ public class EndpointRequestTests {
@Test @Test
public void excludeLinksShouldNotMatchBasePath() { public void excludeLinksShouldNotMatchBasePath() {
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint().excludingLinks(); ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint()
.excludingLinks();
assertMatcher(matcher).doesNotMatch("/actuator"); assertMatcher(matcher).doesNotMatch("/actuator");
assertMatcher(matcher).matches("/actuator/foo"); assertMatcher(matcher).matches("/actuator/foo");
assertMatcher(matcher).matches("/actuator/bar"); assertMatcher(matcher).matches("/actuator/bar");
...@@ -158,7 +159,8 @@ public class EndpointRequestTests { ...@@ -158,7 +159,8 @@ public class EndpointRequestTests {
@Test @Test
public void excludeLinksShouldNotMatchBasePathIfEmptyAndExcluded() { public void excludeLinksShouldNotMatchBasePathIfEmptyAndExcluded() {
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint().excludingLinks(); ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint()
.excludingLinks();
RequestMatcherAssert assertMatcher = assertMatcher(matcher, ""); RequestMatcherAssert assertMatcher = assertMatcher(matcher, "");
assertMatcher.doesNotMatch("/"); assertMatcher.doesNotMatch("/");
assertMatcher.matches("/foo"); assertMatcher.matches("/foo");
...@@ -176,7 +178,8 @@ public class EndpointRequestTests { ...@@ -176,7 +178,8 @@ public class EndpointRequestTests {
return assertMatcher(matcher, mockPathMappedEndpoints("/actuator")); return assertMatcher(matcher, mockPathMappedEndpoints("/actuator"));
} }
private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher, String basePath) { private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher,
String basePath) {
return assertMatcher(matcher, mockPathMappedEndpoints(basePath)); return assertMatcher(matcher, mockPathMappedEndpoints(basePath));
} }
...@@ -200,7 +203,8 @@ public class EndpointRequestTests { ...@@ -200,7 +203,8 @@ public class EndpointRequestTests {
context.registerBean(WebEndpointProperties.class); context.registerBean(WebEndpointProperties.class);
if (pathMappedEndpoints != null) { if (pathMappedEndpoints != null) {
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints); context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
WebEndpointProperties properties = context.getBean(WebEndpointProperties.class); WebEndpointProperties properties = context
.getBean(WebEndpointProperties.class);
if (!properties.getBasePath().equals(pathMappedEndpoints.getBasePath())) { if (!properties.getBasePath().equals(pathMappedEndpoints.getBasePath())) {
properties.setBasePath(pathMappedEndpoints.getBasePath()); properties.setBasePath(pathMappedEndpoints.getBasePath());
} }
......
...@@ -125,8 +125,8 @@ public class EndpointRequestTests { ...@@ -125,8 +125,8 @@ public class EndpointRequestTests {
@Test @Test
public void excludeByClassShouldNotMatchLinksIfExcluded() { public void excludeByClassShouldNotMatchLinksIfExcluded() {
RequestMatcher matcher = EndpointRequest.toAnyEndpoint() RequestMatcher matcher = EndpointRequest.toAnyEndpoint().excludingLinks()
.excludingLinks().excluding(FooEndpoint.class); .excluding(FooEndpoint.class);
assertMatcher(matcher).doesNotMatch("/actuator/foo"); assertMatcher(matcher).doesNotMatch("/actuator/foo");
assertMatcher(matcher).doesNotMatch("/actuator"); assertMatcher(matcher).doesNotMatch("/actuator");
} }
...@@ -141,8 +141,8 @@ public class EndpointRequestTests { ...@@ -141,8 +141,8 @@ public class EndpointRequestTests {
@Test @Test
public void excludeByIdShouldNotMatchLinksIfExcluded() { public void excludeByIdShouldNotMatchLinksIfExcluded() {
RequestMatcher matcher = EndpointRequest.toAnyEndpoint() RequestMatcher matcher = EndpointRequest.toAnyEndpoint().excludingLinks()
.excludingLinks().excluding("foo"); .excluding("foo");
assertMatcher(matcher).doesNotMatch("/actuator/foo"); assertMatcher(matcher).doesNotMatch("/actuator/foo");
assertMatcher(matcher).doesNotMatch("/actuator"); assertMatcher(matcher).doesNotMatch("/actuator");
} }
...@@ -199,7 +199,8 @@ public class EndpointRequestTests { ...@@ -199,7 +199,8 @@ public class EndpointRequestTests {
context.registerBean(WebEndpointProperties.class); context.registerBean(WebEndpointProperties.class);
if (pathMappedEndpoints != null) { if (pathMappedEndpoints != null) {
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints); context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
WebEndpointProperties properties = context.getBean(WebEndpointProperties.class); WebEndpointProperties properties = context
.getBean(WebEndpointProperties.class);
if (!properties.getBasePath().equals(pathMappedEndpoints.getBasePath())) { if (!properties.getBasePath().equals(pathMappedEndpoints.getBasePath())) {
properties.setBasePath(pathMappedEndpoints.getBasePath()); properties.setBasePath(pathMappedEndpoints.getBasePath());
} }
......
...@@ -95,7 +95,8 @@ public class RabbitAutoConfiguration { ...@@ -95,7 +95,8 @@ public class RabbitAutoConfiguration {
@Bean @Bean
public CachingConnectionFactory rabbitConnectionFactory( public CachingConnectionFactory rabbitConnectionFactory(
RabbitProperties properties, RabbitProperties properties,
ObjectProvider<ConnectionNameStrategy> connectionNameStrategy) throws Exception { ObjectProvider<ConnectionNameStrategy> connectionNameStrategy)
throws Exception {
PropertyMapper map = PropertyMapper.get(); PropertyMapper map = PropertyMapper.get();
CachingConnectionFactory factory = new CachingConnectionFactory( CachingConnectionFactory factory = new CachingConnectionFactory(
getRabbitConnectionFactoryBean(properties).getObject()); getRabbitConnectionFactoryBean(properties).getObject());
......
...@@ -91,9 +91,8 @@ class DataSourceInitializedPublisher implements BeanPostProcessor { ...@@ -91,9 +91,8 @@ class DataSourceInitializedPublisher implements BeanPostProcessor {
if (this.properties == null) { if (this.properties == null) {
return true; // better safe than sorry return true; // better safe than sorry
} }
Supplier<String> defaultDdlAuto = () -> Supplier<String> defaultDdlAuto = () -> EmbeddedDatabaseConnection
EmbeddedDatabaseConnection.isEmbedded(dataSource) ? "create-drop" .isEmbedded(dataSource) ? "create-drop" : "none";
: "none";
Map<String, Object> hibernate = this.properties Map<String, Object> hibernate = this.properties
.getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlAuto)); .getHibernateProperties(new HibernateSettings().ddlAuto(defaultDdlAuto));
if (hibernate.containsKey("hibernate.hbm2ddl.auto")) { if (hibernate.containsKey("hibernate.hbm2ddl.auto")) {
......
...@@ -168,7 +168,8 @@ public class RabbitAutoConfigurationTests { ...@@ -168,7 +168,8 @@ public class RabbitAutoConfigurationTests {
DirectFieldAccessor dfa = new DirectFieldAccessor(connectionFactory); DirectFieldAccessor dfa = new DirectFieldAccessor(connectionFactory);
Address[] addresses = (Address[]) dfa.getPropertyValue("addresses"); Address[] addresses = (Address[]) dfa.getPropertyValue("addresses");
assertThat(addresses).hasSize(1); assertThat(addresses).hasSize(1);
com.rabbitmq.client.ConnectionFactory rcf = mock(com.rabbitmq.client.ConnectionFactory.class); com.rabbitmq.client.ConnectionFactory rcf = mock(
com.rabbitmq.client.ConnectionFactory.class);
given(rcf.newConnection(isNull(), eq(addresses), anyString())) given(rcf.newConnection(isNull(), eq(addresses), anyString()))
.willReturn(mock(Connection.class)); .willReturn(mock(Connection.class));
dfa.setPropertyValue("rabbitConnectionFactory", rcf); dfa.setPropertyValue("rabbitConnectionFactory", rcf);
...@@ -787,7 +788,7 @@ public class RabbitAutoConfigurationTests { ...@@ -787,7 +788,7 @@ public class RabbitAutoConfigurationTests {
@Bean @Bean
public ConnectionNameStrategy myConnectionNameStrategy() { public ConnectionNameStrategy myConnectionNameStrategy() {
return c -> "test#" + this.counter.getAndIncrement(); return (connectionFactory) -> "test#" + this.counter.getAndIncrement();
} }
} }
......
...@@ -68,8 +68,8 @@ public class CustomHibernateJpaAutoConfigurationTests { ...@@ -68,8 +68,8 @@ public class CustomHibernateJpaAutoConfigurationTests {
+ "org.hibernate.cfg.naming.ImprovedNamingStrategyDelegator") + "org.hibernate.cfg.naming.ImprovedNamingStrategyDelegator")
.run((context) -> { .run((context) -> {
JpaProperties bean = context.getBean(JpaProperties.class); JpaProperties bean = context.getBean(JpaProperties.class);
Map<String, Object> hibernateProperties = bean.getHibernateProperties( Map<String, Object> hibernateProperties = bean
new HibernateSettings()); .getHibernateProperties(new HibernateSettings());
assertThat(hibernateProperties.get("hibernate.ejb.naming_strategy")) assertThat(hibernateProperties.get("hibernate.ejb.naming_strategy"))
.isNull(); .isNull();
}); });
......
...@@ -29,7 +29,10 @@ import javax.sql.DataSource; ...@@ -29,7 +29,10 @@ import javax.sql.DataSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
...@@ -57,6 +60,14 @@ public class JpaPropertiesTests { ...@@ -57,6 +60,14 @@ public class JpaPropertiesTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class); .withUserConfiguration(TestConfiguration.class);
@Mock
private Supplier<String> ddlAutoSupplier;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test @Test
public void noCustomNamingStrategy() { public void noCustomNamingStrategy() {
this.contextRunner.run(assertJpaProperties((properties) -> { this.contextRunner.run(assertJpaProperties((properties) -> {
...@@ -80,8 +91,7 @@ public class JpaPropertiesTests { ...@@ -80,8 +91,7 @@ public class JpaPropertiesTests {
"spring.jpa.hibernate.naming.physical-strategy:com.example.Physical") "spring.jpa.hibernate.naming.physical-strategy:com.example.Physical")
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(new HibernateSettings());
new HibernateSettings());
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", entry("hibernate.implicit_naming_strategy",
"com.example.Implicit"), "com.example.Implicit"),
...@@ -97,9 +107,8 @@ public class JpaPropertiesTests { ...@@ -97,9 +107,8 @@ public class JpaPropertiesTests {
this.contextRunner.run(assertJpaProperties((properties) -> { this.contextRunner.run(assertJpaProperties((properties) -> {
ImplicitNamingStrategy implicitStrategy = mock(ImplicitNamingStrategy.class); ImplicitNamingStrategy implicitStrategy = mock(ImplicitNamingStrategy.class);
PhysicalNamingStrategy physicalStrategy = mock(PhysicalNamingStrategy.class); PhysicalNamingStrategy physicalStrategy = mock(PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties.getHibernateProperties(
.getHibernateProperties(new HibernateSettings() new HibernateSettings().implicitNamingStrategy(implicitStrategy)
.implicitNamingStrategy(implicitStrategy)
.physicalNamingStrategy(physicalStrategy)); .physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", implicitStrategy), entry("hibernate.implicit_naming_strategy", implicitStrategy),
...@@ -120,10 +129,9 @@ public class JpaPropertiesTests { ...@@ -120,10 +129,9 @@ public class JpaPropertiesTests {
PhysicalNamingStrategy physicalStrategy = mock( PhysicalNamingStrategy physicalStrategy = mock(
PhysicalNamingStrategy.class); PhysicalNamingStrategy.class);
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(new HibernateSettings()
new HibernateSettings() .implicitNamingStrategy(implicitStrategy)
.implicitNamingStrategy(implicitStrategy) .physicalNamingStrategy(physicalStrategy));
.physicalNamingStrategy(physicalStrategy));
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", implicitStrategy), entry("hibernate.implicit_naming_strategy", implicitStrategy),
entry("hibernate.physical_naming_strategy", entry("hibernate.physical_naming_strategy",
...@@ -154,12 +162,11 @@ public class JpaPropertiesTests { ...@@ -154,12 +162,11 @@ public class JpaPropertiesTests {
effectivePhysicalStrategy); effectivePhysicalStrategy);
}; };
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(new HibernateSettings()
new HibernateSettings() .implicitNamingStrategy(implicitStrategy)
.implicitNamingStrategy(implicitStrategy) .physicalNamingStrategy(physicalStrategy)
.physicalNamingStrategy(physicalStrategy) .hibernatePropertiesCustomizers(
.hibernatePropertiesCustomizers( Collections.singleton(customizer)));
Collections.singleton(customizer)));
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", entry("hibernate.implicit_naming_strategy",
effectiveImplicitStrategy), effectiveImplicitStrategy),
...@@ -177,8 +184,7 @@ public class JpaPropertiesTests { ...@@ -177,8 +184,7 @@ public class JpaPropertiesTests {
"spring.jpa.properties.hibernate.physical_naming_strategy:com.example.Physical") "spring.jpa.properties.hibernate.physical_naming_strategy:com.example.Physical")
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(new HibernateSettings());
new HibernateSettings());
// You can override them as we don't provide any default // You can override them as we don't provide any default
assertThat(hibernateProperties).contains( assertThat(hibernateProperties).contains(
entry("hibernate.implicit_naming_strategy", entry("hibernate.implicit_naming_strategy",
...@@ -207,8 +213,7 @@ public class JpaPropertiesTests { ...@@ -207,8 +213,7 @@ public class JpaPropertiesTests {
"spring.jpa.hibernate.use-new-id-generator-mappings:false") "spring.jpa.hibernate.use-new-id-generator-mappings:false")
.run(assertJpaProperties((properties) -> { .run(assertJpaProperties((properties) -> {
Map<String, Object> hibernateProperties = properties Map<String, Object> hibernateProperties = properties
.getHibernateProperties( .getHibernateProperties(new HibernateSettings());
new HibernateSettings());
assertThat(hibernateProperties).containsEntry( assertThat(hibernateProperties).containsEntry(
AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false"); AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "false");
})); }));
...@@ -251,8 +256,7 @@ public class JpaPropertiesTests { ...@@ -251,8 +256,7 @@ public class JpaPropertiesTests {
@Test @Test
public void defaultDdlAutoIsNotInvokedIfPropertyIsSet() { public void defaultDdlAutoIsNotInvokedIfPropertyIsSet() {
this.contextRunner this.contextRunner.withPropertyValues("spring.jpa.hibernate.ddl-auto=validate")
.withPropertyValues("spring.jpa.hibernate.ddl-auto=validate")
.run(assertDefaultDdlAutoNotInvoked("validate")); .run(assertDefaultDdlAutoNotInvoked("validate"));
} }
...@@ -266,13 +270,11 @@ public class JpaPropertiesTests { ...@@ -266,13 +270,11 @@ public class JpaPropertiesTests {
private ContextConsumer<AssertableApplicationContext> assertDefaultDdlAutoNotInvoked( private ContextConsumer<AssertableApplicationContext> assertDefaultDdlAutoNotInvoked(
String expectedDdlAuto) { String expectedDdlAuto) {
return assertJpaProperties((properties) -> { return assertJpaProperties((properties) -> {
Supplier<String> ddlAutoSupplier = mock(Supplier.class); Map<String, Object> hibernateProperties = properties.getHibernateProperties(
Map<String, Object> hibernateProperties = properties new HibernateSettings().ddlAuto(this.ddlAutoSupplier));
.getHibernateProperties(new HibernateSettings() assertThat(hibernateProperties).containsEntry("hibernate.hbm2ddl.auto",
.ddlAuto(ddlAutoSupplier)); expectedDdlAuto);
assertThat(hibernateProperties).containsEntry( verify(this.ddlAutoSupplier, never()).get();
"hibernate.hbm2ddl.auto", expectedDdlAuto);
verify(ddlAutoSupplier, never()).get();
}); });
} }
......
...@@ -48,11 +48,11 @@ public class ResourcePropertiesBindingTests { ...@@ -48,11 +48,11 @@ public class ResourcePropertiesBindingTests {
"spring.resources.static-locations[3]=classpath:/four", "spring.resources.static-locations[3]=classpath:/four",
"spring.resources.static-locations[4]=classpath:/five/", "spring.resources.static-locations[4]=classpath:/five/",
"spring.resources.static-locations[5]=classpath:/six") "spring.resources.static-locations[5]=classpath:/six")
.run(assertResourceProperties((properties) -> .run(assertResourceProperties(
assertThat(properties.getStaticLocations()).contains( (properties) -> assertThat(properties.getStaticLocations())
"classpath:/one/", "classpath:/two/", "classpath:/three/", .contains("classpath:/one/", "classpath:/two/",
"classpath:/four/", "classpath:/five/", "classpath:/three/", "classpath:/four/",
"classpath:/six/"))); "classpath:/five/", "classpath:/six/")));
} }
private ContextConsumer<AssertableApplicationContext> assertResourceProperties( private ContextConsumer<AssertableApplicationContext> assertResourceProperties(
......
...@@ -90,9 +90,11 @@ public class ReactiveWebServerFactoryAutoConfigurationTests { ...@@ -90,9 +90,11 @@ public class ReactiveWebServerFactoryAutoConfigurationTests {
@Test @Test
public void defaultWebServerIsTomcat() { public void defaultWebServerIsTomcat() {
// Tomcat should be chosen over Netty if the Tomcat library is present. // Tomcat should be chosen over Netty if the Tomcat library is present.
this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class).run( this.contextRunner.withUserConfiguration(HttpHandlerConfiguration.class)
(context) -> assertThat(context.getBean(ReactiveWebServerFactory.class)) .withPropertyValues("server.port=0")
.isInstanceOf(TomcatReactiveWebServerFactory.class)); .run((context) -> assertThat(
context.getBean(ReactiveWebServerFactory.class))
.isInstanceOf(TomcatReactiveWebServerFactory.class));
} }
@Configuration @Configuration
......
...@@ -812,12 +812,12 @@ public class WebMvcAutoConfigurationTests { ...@@ -812,12 +812,12 @@ public class WebMvcAutoConfigurationTests {
@Test @Test
public void customConfigurerAppliedAfterAutoConfig() { public void customConfigurerAppliedAfterAutoConfig() {
this.contextRunner this.contextRunner.withUserConfiguration(CustomConfigurer.class)
.withUserConfiguration(CustomConfigurer.class)
.run((context) -> { .run((context) -> {
ContentNegotiationManager manager = context.getBean(ContentNegotiationManager.class); ContentNegotiationManager manager = context
assertThat(manager.getStrategies()).anyMatch(strategy -> .getBean(ContentNegotiationManager.class);
WebMvcAutoConfiguration.OptionalPathExtensionContentNegotiationStrategy.class assertThat(manager.getStrategies()).anyMatch(
strategy -> WebMvcAutoConfiguration.OptionalPathExtensionContentNegotiationStrategy.class
.isAssignableFrom(strategy.getClass())); .isAssignableFrom(strategy.getClass()));
}); });
} }
...@@ -1106,6 +1106,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -1106,6 +1106,7 @@ public class WebMvcAutoConfigurationTests {
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true); configurer.favorPathExtension(true);
} }
} }
} }
...@@ -67,8 +67,10 @@ public class WelcomePageHandlerMappingTests { ...@@ -67,8 +67,10 @@ public class WelcomePageHandlerMappingTests {
public void isOrderedAtLowPriority() { public void isOrderedAtLowPriority() {
this.contextRunner.withUserConfiguration(StaticResourceConfiguration.class) this.contextRunner.withUserConfiguration(StaticResourceConfiguration.class)
.run((context) -> { .run((context) -> {
WelcomePageHandlerMapping handler = context.getBean(WelcomePageHandlerMapping.class); WelcomePageHandlerMapping handler = context
assertThat(handler.getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE - 1); .getBean(WelcomePageHandlerMapping.class);
assertThat(handler.getOrder())
.isEqualTo(Ordered.LOWEST_PRECEDENCE - 1);
}); });
} }
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -371,10 +371,11 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -371,10 +371,11 @@ public class ConfigurationMetadataAnnotationProcessorTests {
ConfigurationMetadata metadata = compile(StaticAccessor.class); ConfigurationMetadata metadata = compile(StaticAccessor.class);
assertThat(metadata) assertThat(metadata)
.has(Metadata.withGroup("specific").fromSource(StaticAccessor.class)); .has(Metadata.withGroup("specific").fromSource(StaticAccessor.class));
assertThat(metadata).has(Metadata.withProperty("specific.counter", assertThat(metadata).has(Metadata.withProperty("specific.counter", Integer.class)
Integer.class).fromSource(StaticAccessor.class).withDefaultValue(42)); .fromSource(StaticAccessor.class).withDefaultValue(42));
assertThat(metadata).doesNotHave(Metadata.withProperty("specific.name", assertThat(metadata)
String.class).fromSource(StaticAccessor.class)); .doesNotHave(Metadata.withProperty("specific.name", String.class)
.fromSource(StaticAccessor.class));
assertThat(metadata.getItems()).hasSize(2); assertThat(metadata.getItems()).hasSize(2);
} }
......
...@@ -46,7 +46,6 @@ import org.springframework.core.env.Environment; ...@@ -46,7 +46,6 @@ import org.springframework.core.env.Environment;
import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/** /**
* A container object which Binds objects from one or more * A container object which Binds objects from one or more
...@@ -309,7 +308,7 @@ public class Binder { ...@@ -309,7 +308,7 @@ public class Binder {
private ConfigurationProperty findProperty(ConfigurationPropertyName name, private ConfigurationProperty findProperty(ConfigurationPropertyName name,
Context context) { Context context) {
if (!StringUtils.hasText(name.toString())) { if (name.isEmpty()) {
return null; return null;
} }
return context.streamSources() return context.streamSources()
......
...@@ -23,6 +23,7 @@ import java.lang.reflect.Method; ...@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
...@@ -126,22 +127,20 @@ class JavaBeanBinder implements BeanBinder { ...@@ -126,22 +127,20 @@ class JavaBeanBinder implements BeanBinder {
} }
private void addMethod(Method method) { private void addMethod(Method method) {
String name = method.getName(); addMethodIfPossible(method, "get", 0, BeanProperty::addGetter);
int parameterCount = method.getParameterCount(); addMethodIfPossible(method, "is", 0, BeanProperty::addGetter);
if (name.startsWith("get") && parameterCount == 0 && name.length() > 3) { addMethodIfPossible(method, "set", 1, BeanProperty::addSetter);
name = Introspector.decapitalize(name.substring(3)); }
this.properties.computeIfAbsent(name, this::getBeanProperty)
.addGetter(method); private void addMethodIfPossible(Method method, String prefix, int parameterCount,
} BiConsumer<BeanProperty, Method> consumer) {
else if (name.startsWith("is") && parameterCount == 0 && name.length() > 2) { if (method.getParameterCount() == parameterCount
name = Introspector.decapitalize(name.substring(2)); && method.getName().startsWith(prefix)
this.properties.computeIfAbsent(name, this::getBeanProperty) && method.getName().length() > prefix.length()) {
.addGetter(method); String propertyName = Introspector
} .decapitalize(method.getName().substring(prefix.length()));
else if (name.startsWith("set") && parameterCount == 1 && name.length() > 3) { consumer.accept(this.properties.computeIfAbsent(propertyName,
name = Introspector.decapitalize(name.substring(3)); this::getBeanProperty), method);
this.properties.computeIfAbsent(name, this::getBeanProperty)
.addSetter(method);
} }
} }
......
...@@ -24,13 +24,28 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyN ...@@ -24,13 +24,28 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyN
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
/** /**
* {@link BindHandler} that can be used to ignore top-level {@link ConverterNotFoundException}s. * {@link BindHandler} that can be used to ignore top-level
* {@link ConverterNotFoundException}s.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
*/ */
public class IgnoreTopLevelConverterNotFoundBindHandler extends AbstractBindHandler { public class IgnoreTopLevelConverterNotFoundBindHandler extends AbstractBindHandler {
/**
* Create a new {@link IgnoreTopLevelConverterNotFoundBindHandler} instance.
*/
public IgnoreTopLevelConverterNotFoundBindHandler() {
}
/**
* Create a new {@link IgnoreTopLevelConverterNotFoundBindHandler} instance with a
* specific parent.
* @param parent the parent handler
*/
public IgnoreTopLevelConverterNotFoundBindHandler(BindHandler parent) {
}
@Override @Override
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target, public Object onFailure(ConfigurationPropertyName name, Bindable<?> target,
BindContext context, Exception error) throws Exception { BindContext context, Exception error) throws Exception {
...@@ -41,5 +56,3 @@ public class IgnoreTopLevelConverterNotFoundBindHandler extends AbstractBindHand ...@@ -41,5 +56,3 @@ public class IgnoreTopLevelConverterNotFoundBindHandler extends AbstractBindHand
} }
} }
...@@ -23,7 +23,6 @@ import java.util.Collections; ...@@ -23,7 +23,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.validation.Validation; import javax.validation.Validation;
...@@ -306,14 +305,13 @@ public class BinderTests { ...@@ -306,14 +305,13 @@ public class BinderTests {
} }
@Test @Test
@SuppressWarnings("unchecked")
public void bindWithEmptyPrefixShouldIgnorePropertiesWithEmptyName() { public void bindWithEmptyPrefixShouldIgnorePropertiesWithEmptyName() {
Map<String, Object> source = new HashMap<>(); Map<String, Object> source = new HashMap<>();
source.put("value", "hello"); source.put("value", "hello");
source.put("", "bar"); source.put("", "bar");
Iterable<ConfigurationPropertySource> propertySources = ConfigurationPropertySources.from( Iterable<ConfigurationPropertySource> propertySources = ConfigurationPropertySources
new MapPropertySource("test", source)); .from(new MapPropertySource("test", source));
this.sources.addAll((Set) propertySources); propertySources.forEach(this.sources::add);
Bindable<JavaBean> target = Bindable.of(JavaBean.class); Bindable<JavaBean> target = Bindable.of(JavaBean.class);
JavaBean result = this.binder.bind("", target).get(); JavaBean result = this.binder.bind("", target).get();
assertThat(result.getValue()).isEqualTo("hello"); assertThat(result.getValue()).isEqualTo("hello");
......
...@@ -70,7 +70,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests { ...@@ -70,7 +70,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests {
@Test @Test
public void bindWhenTopLevelContextAndExceptionIgnorableShouldNotFail() { public void bindWhenTopLevelContextAndExceptionIgnorableShouldNotFail() {
this.binder.bind("example", Bindable.of(Example.class), new IgnoreTopLevelConverterNotFoundBindHandler()); this.binder.bind("example", Bindable.of(Example.class),
new IgnoreTopLevelConverterNotFoundBindHandler());
} }
@Test @Test
...@@ -79,7 +80,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests { ...@@ -79,7 +80,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests {
source.put("example.foo", "1"); source.put("example.foo", "1");
this.sources.add(source); this.sources.add(source);
this.thrown.expectCause(instanceOf(IllegalStateException.class)); this.thrown.expectCause(instanceOf(IllegalStateException.class));
this.binder.bind("example", Bindable.of(Example.class), new IgnoreTopLevelConverterNotFoundBindHandler()); this.binder.bind("example", Bindable.of(Example.class),
new IgnoreTopLevelConverterNotFoundBindHandler());
} }
@Test @Test
...@@ -89,7 +91,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests { ...@@ -89,7 +91,8 @@ public class IgnoreTopLevelConverterNotFoundBindHandlerTests {
this.sources.add(source); this.sources.add(source);
this.thrown.expect(BindException.class); this.thrown.expect(BindException.class);
this.thrown.expectCause(instanceOf(ConverterNotFoundException.class)); this.thrown.expectCause(instanceOf(ConverterNotFoundException.class));
this.binder.bind("example", Bindable.of(Example.class), new IgnoreTopLevelConverterNotFoundBindHandler()); this.binder.bind("example", Bindable.of(Example.class),
new IgnoreTopLevelConverterNotFoundBindHandler());
} }
public static class Example { public static class Example {
......
...@@ -86,8 +86,7 @@ public class SampleActuatorCustomSecurityApplicationTests { ...@@ -86,8 +86,7 @@ public class SampleActuatorCustomSecurityApplicationTests {
ResponseEntity<Object> entity = restTemplate().getForEntity("/actuator", ResponseEntity<Object> entity = restTemplate().getForEntity("/actuator",
Object.class); Object.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
entity = adminRestTemplate().getForEntity("/actuator", entity = adminRestTemplate().getForEntity("/actuator", Object.class);
Object.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
...@@ -137,8 +136,8 @@ public class SampleActuatorCustomSecurityApplicationTests { ...@@ -137,8 +136,8 @@ public class SampleActuatorCustomSecurityApplicationTests {
@Test @Test
public void actuatorExcludedFromEndpointRequestMatcher() { public void actuatorExcludedFromEndpointRequestMatcher() {
ResponseEntity<Object> entity = userRestTemplate().getForEntity("/actuator/mappings", ResponseEntity<Object> entity = userRestTemplate()
Object.class); .getForEntity("/actuator/mappings", Object.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
} }
......
...@@ -95,8 +95,7 @@ public class SampleSecureWebFluxCustomSecurityTests { ...@@ -95,8 +95,7 @@ public class SampleSecureWebFluxCustomSecurityTests {
@Test @Test
public void actuatorLinksIsSecure() { public void actuatorLinksIsSecure() {
this.webClient.get().uri("/actuator").accept(MediaType.APPLICATION_JSON) this.webClient.get().uri("/actuator").accept(MediaType.APPLICATION_JSON)
.exchange() .exchange().expectStatus().isUnauthorized();
.expectStatus().isUnauthorized();
this.webClient.get().uri("/actuator").accept(MediaType.APPLICATION_JSON) this.webClient.get().uri("/actuator").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "basic " + getBasicAuthForAdmin()).exchange() .header("Authorization", "basic " + getBasicAuthForAdmin()).exchange()
.expectStatus().isOk(); .expectStatus().isOk();
...@@ -118,7 +117,9 @@ public class SampleSecureWebFluxCustomSecurityTests { ...@@ -118,7 +117,9 @@ public class SampleSecureWebFluxCustomSecurityTests {
@Bean @Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange().matchers(EndpointRequest.to("health", "info")) http.authorizeExchange().matchers(EndpointRequest.to("health", "info"))
.permitAll().matchers(EndpointRequest.toAnyEndpoint().excluding(MappingsEndpoint.class)) .permitAll()
.matchers(EndpointRequest.toAnyEndpoint()
.excluding(MappingsEndpoint.class))
.hasRole("ACTUATOR") .hasRole("ACTUATOR")
.matchers(PathRequest.toStaticResources().atCommonLocations()) .matchers(PathRequest.toStaticResources().atCommonLocations())
.permitAll().pathMatchers("/login").permitAll().anyExchange() .permitAll().pathMatchers("/login").permitAll().anyExchange()
......
...@@ -44,7 +44,6 @@ public abstract class AbstractEmbeddedServletContainerIntegrationTests { ...@@ -44,7 +44,6 @@ public abstract class AbstractEmbeddedServletContainerIntegrationTests {
@Override @Override
public void delete() { public void delete() {
} }
}; };
......
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