Commit 7bc535e4 authored by Phillip Webb's avatar Phillip Webb

Polish

parent 67998e98
...@@ -95,8 +95,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi ...@@ -95,8 +95,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) { ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) {
Set<PathPattern> patterns = mapping.getPatternsCondition().getPatterns(); Set<PathPattern> patterns = mapping.getPatternsCondition().getPatterns();
if (patterns.isEmpty()) { if (patterns.isEmpty()) {
patterns = new HashSet<>( patterns = new HashSet<>(Arrays.asList(getPathPatternParser().parse("")));
Arrays.asList(getPathPatternParser().parse("")));
} }
PathPattern[] endpointMappedPatterns = patterns.stream() PathPattern[] endpointMappedPatterns = patterns.stream()
.map((pattern) -> getEndpointMappedPattern(endpoint, pattern)) .map((pattern) -> getEndpointMappedPattern(endpoint, pattern))
......
...@@ -64,8 +64,8 @@ class DataSourceJmxConfiguration { ...@@ -64,8 +64,8 @@ class DataSourceJmxConfiguration {
public void validateMBeans() { public void validateMBeans() {
HikariDataSource hikariDataSource = unwrapHikariDataSource(); HikariDataSource hikariDataSource = unwrapHikariDataSource();
if (hikariDataSource != null && hikariDataSource.isRegisterMbeans()) { if (hikariDataSource != null && hikariDataSource.isRegisterMbeans()) {
this.mBeanExporter.ifUnique((exporter) -> this.mBeanExporter
exporter.addExcludedBean("dataSource")); .ifUnique((exporter) -> exporter.addExcludedBean("dataSource"));
} }
} }
......
...@@ -218,12 +218,10 @@ public class EmbeddedLdapAutoConfiguration { ...@@ -218,12 +218,10 @@ public class EmbeddedLdapAutoConfiguration {
AnnotatedTypeMetadata metadata) { AnnotatedTypeMetadata metadata) {
Builder message = ConditionMessage.forCondition("Embedded LDAP"); Builder message = ConditionMessage.forCondition("Embedded LDAP");
Environment environment = context.getEnvironment(); Environment environment = context.getEnvironment();
if (environment != null if (environment != null && !Binder.get(environment)
&& !Binder.get(environment) .bind("spring.ldap.embedded.base-dn", STRING_LIST)
.bind("spring.ldap.embedded.base-dn", STRING_LIST) .orElseGet(Collections::emptyList).isEmpty()) {
.orElseGet(Collections::emptyList).isEmpty()) { return ConditionOutcome.match(message.because("Found base-dn property"));
return ConditionOutcome
.match(message.because("Found base-dn property"));
} }
return ConditionOutcome.noMatch(message.because("No base-dn property found")); return ConditionOutcome.noMatch(message.because("No base-dn property found"));
} }
......
...@@ -75,8 +75,8 @@ public class ConditionEvaluationReportLoggingListener ...@@ -75,8 +75,8 @@ public class ConditionEvaluationReportLoggingListener
} }
} }
else if (event instanceof ApplicationFailedEvent else if (event instanceof ApplicationFailedEvent
&& ((ApplicationFailedEvent) event) && ((ApplicationFailedEvent) event)
.getApplicationContext() == initializerApplicationContext) { .getApplicationContext() == initializerApplicationContext) {
logAutoConfigurationReport(true); logAutoConfigurationReport(true);
} }
} }
......
...@@ -49,24 +49,26 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -49,24 +49,26 @@ import static org.assertj.core.api.Assertions.assertThat;
public class DataSourceJmxConfigurationTests { public class DataSourceJmxConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.datasource.url=" .withPropertyValues("spring.datasource.url=" + "jdbc:hsqldb:mem:test-"
+ "jdbc:hsqldb:mem:test-" + UUID.randomUUID()) + UUID.randomUUID())
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class,
DataSourceAutoConfiguration.class)); DataSourceAutoConfiguration.class));
@Test @Test
public void hikariAutoConfiguredCanUseRegisterMBeans() { public void hikariAutoConfiguredCanUseRegisterMBeans() {
String poolName = UUID.randomUUID().toString(); String poolName = UUID.randomUUID().toString();
this.contextRunner.withPropertyValues( this.contextRunner
"spring.datasource.type=" + HikariDataSource.class.getName(), .withPropertyValues(
"spring.datasource.name=" + poolName, "spring.datasource.type=" + HikariDataSource.class.getName(),
"spring.datasource.hikari.register-mbeans=true").run((context) -> { "spring.datasource.name=" + poolName,
assertThat(context).hasSingleBean(HikariDataSource.class); "spring.datasource.hikari.register-mbeans=true")
assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans()) .run((context) -> {
.isTrue(); assertThat(context).hasSingleBean(HikariDataSource.class);
MBeanServer mBeanServer = context.getBean(MBeanServer.class); assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans())
validateHikariMBeansRegistration(mBeanServer, poolName, true); .isTrue();
}); MBeanServer mBeanServer = context.getBean(MBeanServer.class);
validateHikariMBeansRegistration(mBeanServer, poolName, true);
});
} }
@Test @Test
...@@ -75,34 +77,39 @@ public class DataSourceJmxConfigurationTests { ...@@ -75,34 +77,39 @@ public class DataSourceJmxConfigurationTests {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectInstance> existingInstances = mBeanServer Set<ObjectInstance> existingInstances = mBeanServer
.queryMBeans(new ObjectName("com.zaxxer.hikari:type=*"), null); .queryMBeans(new ObjectName("com.zaxxer.hikari:type=*"), null);
this.contextRunner.withPropertyValues( this.contextRunner
"spring.datasource.type=" + HikariDataSource.class.getName(), .withPropertyValues(
"spring.datasource.hikari.register-mbeans=true").run((context) -> { "spring.datasource.type=" + HikariDataSource.class.getName(),
assertThat(context).hasSingleBean(HikariDataSource.class); "spring.datasource.hikari.register-mbeans=true")
assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans()) .run((context) -> {
.isTrue(); assertThat(context).hasSingleBean(HikariDataSource.class);
// We can't rely on the number of MBeans so we're checking that the pool and pool assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans())
// config MBeans were registered .isTrue();
assertThat(mBeanServer // We can't rely on the number of MBeans so we're checking that the
.queryMBeans(new ObjectName("com.zaxxer.hikari:type=*"), null).size()) // pool and pool
.isEqualTo(existingInstances.size() + 2); // config MBeans were registered
}); assertThat(mBeanServer
.queryMBeans(new ObjectName("com.zaxxer.hikari:type=*"), null)
.size()).isEqualTo(existingInstances.size() + 2);
});
} }
@Test @Test
public void hikariAutoConfiguredUsesJmsFlag() { public void hikariAutoConfiguredUsesJmsFlag() {
String poolName = UUID.randomUUID().toString(); String poolName = UUID.randomUUID().toString();
this.contextRunner.withPropertyValues( this.contextRunner
"spring.datasource.type=" + HikariDataSource.class.getName(), .withPropertyValues(
"spring.jmx.enabled=false", "spring.datasource.name=" + poolName, "spring.datasource.type=" + HikariDataSource.class.getName(),
"spring.datasource.hikari.register-mbeans=true").run((context) -> { "spring.jmx.enabled=false", "spring.datasource.name=" + poolName,
assertThat(context).hasSingleBean(HikariDataSource.class); "spring.datasource.hikari.register-mbeans=true")
assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans()) .run((context) -> {
.isTrue(); assertThat(context).hasSingleBean(HikariDataSource.class);
// Hikari can still register mBeans assertThat(context.getBean(HikariDataSource.class).isRegisterMbeans())
validateHikariMBeansRegistration(ManagementFactory.getPlatformMBeanServer(), .isTrue();
poolName, true); // Hikari can still register mBeans
}); validateHikariMBeansRegistration(
ManagementFactory.getPlatformMBeanServer(), poolName, true);
});
} }
@Test @Test
...@@ -115,8 +122,9 @@ public class DataSourceJmxConfigurationTests { ...@@ -115,8 +122,9 @@ public class DataSourceJmxConfigurationTests {
"spring.datasource.hikari.register-mbeans=true") "spring.datasource.hikari.register-mbeans=true")
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(javax.sql.DataSource.class); assertThat(context).hasSingleBean(javax.sql.DataSource.class);
HikariDataSource hikariDataSource = context.getBean( HikariDataSource hikariDataSource = context
javax.sql.DataSource.class).unwrap(HikariDataSource.class); .getBean(javax.sql.DataSource.class)
.unwrap(HikariDataSource.class);
assertThat(hikariDataSource.isRegisterMbeans()).isTrue(); assertThat(hikariDataSource.isRegisterMbeans()).isTrue();
MBeanServer mBeanServer = context.getBean(MBeanServer.class); MBeanServer mBeanServer = context.getBean(MBeanServer.class);
validateHikariMBeansRegistration(mBeanServer, poolName, true); validateHikariMBeansRegistration(mBeanServer, poolName, true);
...@@ -127,18 +135,19 @@ public class DataSourceJmxConfigurationTests { ...@@ -127,18 +135,19 @@ public class DataSourceJmxConfigurationTests {
String poolName, boolean expected) throws MalformedObjectNameException { String poolName, boolean expected) throws MalformedObjectNameException {
assertThat(mBeanServer.isRegistered( assertThat(mBeanServer.isRegistered(
new ObjectName("com.zaxxer.hikari:type=Pool (" + poolName + ")"))) new ObjectName("com.zaxxer.hikari:type=Pool (" + poolName + ")")))
.isEqualTo(expected); .isEqualTo(expected);
assertThat(mBeanServer.isRegistered( assertThat(mBeanServer.isRegistered(
new ObjectName("com.zaxxer.hikari:type=PoolConfig (" + poolName + ")"))) new ObjectName("com.zaxxer.hikari:type=PoolConfig (" + poolName + ")")))
.isEqualTo(expected); .isEqualTo(expected);
} }
@Test @Test
public void tomcatDoesNotExposeMBeanPoolByDefault() { public void tomcatDoesNotExposeMBeanPoolByDefault() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.datasource.type=" + DataSource.class.getName()) .withPropertyValues(
.run((context) -> "spring.datasource.type=" + DataSource.class.getName())
assertThat(context).doesNotHaveBean(ConnectionPool.class)); .run((context) -> assertThat(context)
.doesNotHaveBean(ConnectionPool.class));
} }
@Test @Test
...@@ -146,10 +155,11 @@ public class DataSourceJmxConfigurationTests { ...@@ -146,10 +155,11 @@ public class DataSourceJmxConfigurationTests {
this.contextRunner.withPropertyValues( this.contextRunner.withPropertyValues(
"spring.datasource.type=" + DataSource.class.getName(), "spring.datasource.type=" + DataSource.class.getName(),
"spring.datasource.jmx-enabled=true").run((context) -> { "spring.datasource.jmx-enabled=true").run((context) -> {
assertThat(context).hasSingleBean(ConnectionPool.class); assertThat(context).hasSingleBean(ConnectionPool.class);
assertThat(context.getBean(DataSourceProxy.class).createPool().getJmxPool()) assertThat(context.getBean(DataSourceProxy.class).createPool()
.isSameAs(context.getBean(ConnectionPool.class)); .getJmxPool())
}); .isSameAs(context.getBean(ConnectionPool.class));
});
} }
@Configuration @Configuration
...@@ -162,7 +172,6 @@ public class DataSourceJmxConfigurationTests { ...@@ -162,7 +172,6 @@ public class DataSourceJmxConfigurationTests {
} }
private static class DataSourceBeanPostProcessor implements BeanPostProcessor { private static class DataSourceBeanPostProcessor implements BeanPostProcessor {
@Override @Override
......
/* /*
* 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.
...@@ -22,8 +22,6 @@ import java.io.IOException; ...@@ -22,8 +22,6 @@ import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.assertj.core.api.Condition;
import org.assertj.core.description.Description;
import org.assertj.core.description.TextDescription; import org.assertj.core.description.TextDescription;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
......
...@@ -266,8 +266,7 @@ final class JarURLConnection extends java.net.JarURLConnection { ...@@ -266,8 +266,7 @@ final class JarURLConnection extends java.net.JarURLConnection {
index = separator + SEPARATOR.length(); index = separator + SEPARATOR.length();
} }
JarEntryName jarEntryName = JarEntryName.get(spec, index); JarEntryName jarEntryName = JarEntryName.get(spec, index);
if (Boolean.TRUE.equals(useFastExceptions.get()) if (Boolean.TRUE.equals(useFastExceptions.get()) && !jarEntryName.isEmpty()
&& !jarEntryName.isEmpty()
&& !jarFile.containsEntry(jarEntryName.toString())) { && !jarFile.containsEntry(jarEntryName.toString())) {
return NOT_FOUND_CONNECTION; return NOT_FOUND_CONNECTION;
} }
......
/* /*
* 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.
......
...@@ -142,8 +142,7 @@ public class ApplicationPidFileWriter ...@@ -142,8 +142,7 @@ public class ApplicationPidFileWriter
writePidFile(event); writePidFile(event);
} }
catch (Exception ex) { catch (Exception ex) {
String message = String.format("Cannot create pid file %s", String message = String.format("Cannot create pid file %s", this.file);
this.file);
if (failOnWriteError(event)) { if (failOnWriteError(event)) {
throw new IllegalStateException(message, ex); throw new IllegalStateException(message, ex);
} }
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
package org.springframework.boot.web.embedded.netty; package org.springframework.boot.web.embedded.netty;
import java.util.Arrays;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaders;
import reactor.ipc.netty.http.server.HttpServerOptions; import reactor.ipc.netty.http.server.HttpServerOptions;
import reactor.ipc.netty.http.server.HttpServerRequest; import reactor.ipc.netty.http.server.HttpServerRequest;
import reactor.ipc.netty.http.server.HttpServerResponse; import reactor.ipc.netty.http.server.HttpServerResponse;
...@@ -26,11 +28,14 @@ import reactor.ipc.netty.http.server.HttpServerResponse; ...@@ -26,11 +28,14 @@ import reactor.ipc.netty.http.server.HttpServerResponse;
import org.springframework.boot.web.server.Compression; import org.springframework.boot.web.server.Compression;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils; import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/** /**
* Configure the HTTP compression on an Reactor Netty request/response handler. * Configure the HTTP compression on an Reactor Netty request/response handler.
* *
* @author Stephane Maldini * @author Stephane Maldini
* @author Phillip Webb
*/ */
final class CompressionCustomizer implements NettyServerCustomizer { final class CompressionCustomizer implements NettyServerCustomizer {
...@@ -45,71 +50,46 @@ final class CompressionCustomizer implements NettyServerCustomizer { ...@@ -45,71 +50,46 @@ final class CompressionCustomizer implements NettyServerCustomizer {
if (this.compression.getMinResponseSize() >= 0) { if (this.compression.getMinResponseSize() >= 0) {
builder.compression(this.compression.getMinResponseSize()); builder.compression(this.compression.getMinResponseSize());
} }
BiPredicate<HttpServerRequest, HttpServerResponse> compressPredicate = null; CompressionPredicate mimeTypes = getMimeTypesPredicate(
if (this.compression.getMimeTypes() != null && this.compression.getMimeTypes());
this.compression.getMimeTypes().length > 0) { CompressionPredicate excludedUserAgents = getExcludedUserAgentsPredicate(
compressPredicate = new CompressibleMimeTypePredicate(this.compression.getMimeTypes()); this.compression.getExcludedUserAgents());
} builder.compression(mimeTypes.and(excludedUserAgents));
if (this.compression.getExcludedUserAgents() != null &&
this.compression.getExcludedUserAgents().length > 0) {
BiPredicate<HttpServerRequest, HttpServerResponse> agentCompressPredicate =
new CompressibleAgentPredicate(this.compression.getExcludedUserAgents());
compressPredicate = compressPredicate == null ?
agentCompressPredicate :
compressPredicate.and(agentCompressPredicate);
}
if (compressPredicate != null) {
builder.compression(compressPredicate);
}
} }
private static class CompressibleAgentPredicate private CompressionPredicate getMimeTypesPredicate(String[] mimeTypes) {
implements BiPredicate<HttpServerRequest, HttpServerResponse> { if (ObjectUtils.isEmpty(mimeTypes)) {
return CompressionPredicate.ALWAYS;
private final String[] excludedAgents;
CompressibleAgentPredicate(String[] excludedAgents) {
this.excludedAgents = new String[excludedAgents.length];
System.arraycopy(excludedAgents, 0, this.excludedAgents, 0, excludedAgents.length);
} }
return (request, response) -> {
@Override String contentType = response.responseHeaders()
public boolean test(HttpServerRequest request, HttpServerResponse response) { .get(HttpHeaderNames.CONTENT_TYPE);
for (String excludedAgent : this.excludedAgents) { if (StringUtils.isEmpty(contentType)) {
if (request.requestHeaders() return false;
.contains(HttpHeaderNames.USER_AGENT, excludedAgent, true)) {
return false;
}
} }
return true; MimeType contentMimeType = MimeTypeUtils.parseMimeType(contentType);
} return Arrays.stream(mimeTypes).map(MimeTypeUtils::parseMimeType)
.anyMatch((candidate) -> candidate.isCompatibleWith(contentMimeType));
};
} }
private static class CompressibleMimeTypePredicate private CompressionPredicate getExcludedUserAgentsPredicate(
implements BiPredicate<HttpServerRequest, HttpServerResponse> { String[] excludedUserAgents) {
if (ObjectUtils.isEmpty(excludedUserAgents)) {
private final MimeType[] mimeTypes; return CompressionPredicate.ALWAYS;
CompressibleMimeTypePredicate(String[] mimeTypes) {
this.mimeTypes = new MimeType[mimeTypes.length];
for (int i = 0; i < mimeTypes.length; i++) {
this.mimeTypes[i] = MimeTypeUtils.parseMimeType(mimeTypes[i]);
}
} }
return (request, response) -> {
HttpHeaders headers = request.requestHeaders();
return Arrays.stream(excludedUserAgents).noneMatch((candidate) -> headers
.contains(HttpHeaderNames.USER_AGENT, candidate, true));
};
}
@Override private interface CompressionPredicate
public boolean test(HttpServerRequest request, HttpServerResponse response) { extends BiPredicate<HttpServerRequest, HttpServerResponse> {
String contentType = response.responseHeaders()
.get(HttpHeaderNames.CONTENT_TYPE); static final CompressionPredicate ALWAYS = (request, response) -> true;
if (contentType != null) {
for (MimeType mimeType : this.mimeTypes) {
if (mimeType.isCompatibleWith(MimeTypeUtils.parseMimeType(contentType))) {
return true;
}
}
}
return false;
}
} }
} }
...@@ -286,7 +286,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { ...@@ -286,7 +286,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
@Test @Test
public void noCompressionForMimeType() { public void noCompressionForMimeType() {
Compression compression = new Compression(); Compression compression = new Compression();
compression.setMimeTypes(new String[] {"application/json"}); compression.setMimeTypes(new String[] { "application/json" });
WebClient client = prepareCompressionTest(compression); WebClient client = prepareCompressionTest(compression);
ResponseEntity<Void> response = client.get().exchange() ResponseEntity<Void> response = client.get().exchange()
.flatMap((res) -> res.toEntity(Void.class)).block(); .flatMap((res) -> res.toEntity(Void.class)).block();
...@@ -297,7 +297,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { ...@@ -297,7 +297,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
public void noCompressionForUserAgent() { public void noCompressionForUserAgent() {
Compression compression = new Compression(); Compression compression = new Compression();
compression.setEnabled(true); compression.setEnabled(true);
compression.setExcludedUserAgents(new String[] {"testUserAgent"}); compression.setExcludedUserAgents(new String[] { "testUserAgent" });
WebClient client = prepareCompressionTest(compression); WebClient client = prepareCompressionTest(compression);
ResponseEntity<Void> response = client.get().header("User-Agent", "testUserAgent") ResponseEntity<Void> response = client.get().header("User-Agent", "testUserAgent")
.exchange().flatMap((res) -> res.toEntity(Void.class)).block(); .exchange().flatMap((res) -> res.toEntity(Void.class)).block();
......
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