/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet;
import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import org.apache.catalina.Context;
import org.apache.catalina.Valve;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.AbstractProtocol;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.RequestLog;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link DefaultServletWebServerFactoryCustomizer}.
*
* @author Brian Clozel
*/
public class DefaultServletWebServerFactoryCustomizerTests {
private final ServerProperties properties = new ServerProperties();
private DefaultServletWebServerFactoryCustomizer customizer;
@Captor
private ArgumentCaptor<ServletContextInitializer[]> initializersCaptor;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.customizer = new DefaultServletWebServerFactoryCustomizer(this.properties);
}
@Test
public void tomcatAccessLogIsDisabledByDefault() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getEngineValves()).isEmpty();
}
@Test
public void tomcatAccessLogCanBeEnabled() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
assertThat(factory.getEngineValves()).hasSize(1);
assertThat(factory.getEngineValves()).first().isInstanceOf(AccessLogValve.class);
}
@Test
public void tomcatAccessLogFileDateFormatByDefault() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Map<String, String> map = new HashMap<String, String>();
map.put("server.tomcat.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
assertThat(((AccessLogValve) factory.getEngineValves().iterator().next())
.getFileDateFormat()).isEqualTo(".yyyy-MM-dd");
}
@Test
public void tomcatAccessLogFileDateFormatCanBeRedefined() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Map<String, String> map = new HashMap<String, String>();
map.put("server.tomcat.accesslog.enabled", "true");
map.put("server.tomcat.accesslog.file-date-format", "yyyy-MM-dd.HH");
bindProperties(map);
this.customizer.customize(factory);
assertThat(((AccessLogValve) factory.getEngineValves().iterator().next())
.getFileDateFormat()).isEqualTo("yyyy-MM-dd.HH");
}
@Test
public void tomcatAccessLogIsBufferedByDefault() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
assertThat(((AccessLogValve) factory.getEngineValves().iterator().next())
.isBuffered()).isTrue();
}
@Test
public void tomcatAccessLogBufferingCanBeDisabled() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.accesslog.enabled", "true");
map.put("server.tomcat.accesslog.buffered", "false");
bindProperties(map);
this.customizer.customize(factory);
assertThat(((AccessLogValve) factory.getEngineValves().iterator().next())
.isBuffered()).isFalse();
}
@Test
public void redirectContextRootCanBeConfigured() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.redirect-context-root", "false");
bindProperties(map);
ServerProperties.Tomcat tomcat = this.properties.getTomcat();
assertThat(tomcat.getRedirectContextRoot()).isEqualTo(false);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
Context context = mock(Context.class);
for (TomcatContextCustomizer customizer : factory.getTomcatContextCustomizers()) {
customizer.customize(context);
}
verify(context).setMapperContextRootRedirectEnabled(false);
}
@Test
public void testCustomizeTomcat() throws Exception {
ConfigurableServletWebServerFactory factory = mock(
ConfigurableServletWebServerFactory.class);
this.customizer.customize(factory);
verify(factory, never()).setContextPath("");
}
@Test
public void testDefaultDisplayName() throws Exception {
ConfigurableServletWebServerFactory factory = mock(
ConfigurableServletWebServerFactory.class);
this.customizer.customize(factory);
verify(factory).setDisplayName("application");
}
@Test
public void testCustomizeDisplayName() throws Exception {
ConfigurableServletWebServerFactory factory = mock(
ConfigurableServletWebServerFactory.class);
this.properties.setDisplayName("TestName");
this.customizer.customize(factory);
verify(factory).setDisplayName("TestName");
}
@Test
public void customizeSessionProperties() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.session.timeout", "123");
map.put("server.session.tracking-modes", "cookie,url");
map.put("server.session.cookie.name", "testname");
map.put("server.session.cookie.domain", "testdomain");
map.put("server.session.cookie.path", "/testpath");
map.put("server.session.cookie.comment", "testcomment");
map.put("server.session.cookie.http-only", "true");
map.put("server.session.cookie.secure", "true");
map.put("server.session.cookie.max-age", "60");
bindProperties(map);
ConfigurableServletWebServerFactory factory = mock(
ConfigurableServletWebServerFactory.class);
ServletContext servletContext = mock(ServletContext.class);
SessionCookieConfig sessionCookieConfig = mock(SessionCookieConfig.class);
given(servletContext.getSessionCookieConfig()).willReturn(sessionCookieConfig);
this.customizer.customize(factory);
triggerInitializers(factory, servletContext);
verify(factory).setSessionTimeout(123);
verify(servletContext).setSessionTrackingModes(
EnumSet.of(SessionTrackingMode.COOKIE, SessionTrackingMode.URL));
verify(sessionCookieConfig).setName("testname");
verify(sessionCookieConfig).setDomain("testdomain");
verify(sessionCookieConfig).setPath("/testpath");
verify(sessionCookieConfig).setComment("testcomment");
verify(sessionCookieConfig).setHttpOnly(true);
verify(sessionCookieConfig).setSecure(true);
verify(sessionCookieConfig).setMaxAge(60);
}
@Test
public void testCustomizeTomcatPort() throws Exception {
ConfigurableServletWebServerFactory factory = mock(
ConfigurableServletWebServerFactory.class);
this.properties.setPort(8080);
this.customizer.customize(factory);
verify(factory).setPort(8080);
}
@Test
public void customizeTomcatDisplayName() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.display-name", "MyBootApp");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getDisplayName()).isEqualTo("MyBootApp");
}
@Test
public void disableTomcatRemoteIpValve() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.remote-ip-header", "");
map.put("server.tomcat.protocol-header", "");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getEngineValves()).isEmpty();
}
@Test
public void defaultTomcatBackgroundProcessorDelay() throws Exception {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
TomcatWebServer webServer = (TomcatWebServer) factory.getWebServer();
assertThat(webServer.getTomcat().getEngine().getBackgroundProcessorDelay())
.isEqualTo(30);
webServer.stop();
}
@Test
public void customTomcatBackgroundProcessorDelay() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.background-processor-delay", "5");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
TomcatWebServer webServer = (TomcatWebServer) factory.getWebServer();
assertThat(webServer.getTomcat().getEngine().getBackgroundProcessorDelay())
.isEqualTo(5);
webServer.stop();
}
@Test
public void defaultTomcatRemoteIpValve() throws Exception {
Map<String, String> map = new HashMap<>();
// Since 1.1.7 you need to specify at least the protocol
map.put("server.tomcat.protocol-header", "X-Forwarded-Proto");
map.put("server.tomcat.remote-ip-header", "X-Forwarded-For");
bindProperties(map);
testRemoteIpValveConfigured();
}
@Test
public void setUseForwardHeadersTomcat() throws Exception {
// Since 1.3.0 no need to explicitly set header names if use-forward-header=true
this.properties.setUseForwardHeaders(true);
testRemoteIpValveConfigured();
}
@Test
public void deduceUseForwardHeadersTomcat() throws Exception {
this.customizer.setEnvironment(new MockEnvironment().withProperty("DYNO", "-"));
testRemoteIpValveConfigured();
}
private void testRemoteIpValveConfigured() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getEngineValves()).hasSize(1);
Valve valve = factory.getEngineValves().iterator().next();
assertThat(valve).isInstanceOf(RemoteIpValve.class);
RemoteIpValve remoteIpValve = (RemoteIpValve) valve;
assertThat(remoteIpValve.getProtocolHeader()).isEqualTo("X-Forwarded-Proto");
assertThat(remoteIpValve.getProtocolHeaderHttpsValue()).isEqualTo("https");
assertThat(remoteIpValve.getRemoteIpHeader()).isEqualTo("X-Forwarded-For");
String expectedInternalProxies = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 10/8
+ "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" // 192.168/16
+ "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" // 169.254/16
+ "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 127/8
+ "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" // 172.16/12
+ "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|"
+ "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}";
assertThat(remoteIpValve.getInternalProxies()).isEqualTo(expectedInternalProxies);
}
@Test
public void customTomcatRemoteIpValve() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.remote-ip-header", "x-my-remote-ip-header");
map.put("server.tomcat.protocol-header", "x-my-protocol-header");
map.put("server.tomcat.internal-proxies", "192.168.0.1");
map.put("server.tomcat.port-header", "x-my-forward-port");
map.put("server.tomcat.protocol-header-https-value", "On");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getEngineValves()).hasSize(1);
Valve valve = factory.getEngineValves().iterator().next();
assertThat(valve).isInstanceOf(RemoteIpValve.class);
RemoteIpValve remoteIpValve = (RemoteIpValve) valve;
assertThat(remoteIpValve.getProtocolHeader()).isEqualTo("x-my-protocol-header");
assertThat(remoteIpValve.getProtocolHeaderHttpsValue()).isEqualTo("On");
assertThat(remoteIpValve.getRemoteIpHeader()).isEqualTo("x-my-remote-ip-header");
assertThat(remoteIpValve.getPortHeader()).isEqualTo("x-my-forward-port");
assertThat(remoteIpValve.getInternalProxies()).isEqualTo("192.168.0.1");
}
@Test
public void customTomcatAcceptCount() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.accept-count", "10");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
this.customizer.customize(factory);
TomcatWebServer embeddedFactory = (TomcatWebServer) factory.getWebServer();
embeddedFactory.start();
try {
assertThat(((AbstractProtocol<?>) embeddedFactory.getTomcat().getConnector()
.getProtocolHandler()).getBacklog()).isEqualTo(10);
}
finally {
embeddedFactory.stop();
}
}
@Test
public void customTomcatMaxConnections() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.max-connections", "5");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
this.customizer.customize(factory);
TomcatWebServer embeddedFactory = (TomcatWebServer) factory.getWebServer();
embeddedFactory.start();
try {
assertThat(((AbstractProtocol<?>) embeddedFactory.getTomcat().getConnector()
.getProtocolHandler()).getMaxConnections()).isEqualTo(5);
}
finally {
embeddedFactory.stop();
}
}
@Test
public void customTomcatMaxHttpPostSize() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.max-http-post-size", "10000");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
this.customizer.customize(factory);
TomcatWebServer embeddedFactory = (TomcatWebServer) factory.getWebServer();
embeddedFactory.start();
try {
assertThat(embeddedFactory.getTomcat().getConnector().getMaxPostSize())
.isEqualTo(10000);
}
finally {
embeddedFactory.stop();
}
}
@Test
public void customTomcatDisableMaxHttpPostSize() {
Map<String, String> map = new HashMap<String, String>();
map.put("server.tomcat.max-http-post-size", "-1");
bindProperties(map);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
this.customizer.customize(factory);
TomcatWebServer embeddedFactory = (TomcatWebServer) factory.getWebServer();
embeddedFactory.start();
try {
assertThat(embeddedFactory.getTomcat().getConnector().getMaxPostSize())
.isEqualTo(-1);
}
finally {
embeddedFactory.stop();
}
}
@Test
public void customizeUndertowAccessLog() {
Map<String, String> map = new HashMap<>();
map.put("server.undertow.accesslog.enabled", "true");
map.put("server.undertow.accesslog.pattern", "foo");
map.put("server.undertow.accesslog.prefix", "test_log");
map.put("server.undertow.accesslog.suffix", "txt");
map.put("server.undertow.accesslog.dir", "test-logs");
map.put("server.undertow.accesslog.rotate", "false");
bindProperties(map);
UndertowServletWebServerFactory factory = spy(
new UndertowServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setAccessLogEnabled(true);
verify(factory).setAccessLogPattern("foo");
verify(factory).setAccessLogPrefix("test_log");
verify(factory).setAccessLogSuffix("txt");
verify(factory).setAccessLogDirectory(new File("test-logs"));
verify(factory).setAccessLogRotate(false);
}
@Test
public void testCustomizeTomcatMinSpareThreads() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.min-spare-threads", "10");
bindProperties(map);
assertThat(this.properties.getTomcat().getMinSpareThreads()).isEqualTo(10);
}
@Test
public void customTomcatTldSkip() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.additional-tld-skip-patterns", "foo.jar,bar.jar");
bindProperties(map);
testCustomTomcatTldSkip("foo.jar", "bar.jar");
}
@Test
public void customTomcatTldSkipAsList() {
Map<String, String> map = new HashMap<>();
map.put("server.tomcat.additional-tld-skip-patterns[0]", "biz.jar");
map.put("server.tomcat.additional-tld-skip-patterns[1]", "bah.jar");
bindProperties(map);
testCustomTomcatTldSkip("biz.jar", "bah.jar");
}
private void testCustomTomcatTldSkip(String... expectedJars) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
this.customizer.customize(factory);
assertThat(factory.getTldSkipPatterns()).contains(expectedJars);
assertThat(factory.getTldSkipPatterns()).contains("junit-*.jar",
"spring-boot-*.jar");
}
@Test
public void defaultUseForwardHeadersUndertow() throws Exception {
UndertowServletWebServerFactory factory = spy(
new UndertowServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(false);
}
@Test
public void setUseForwardHeadersUndertow() throws Exception {
this.properties.setUseForwardHeaders(true);
UndertowServletWebServerFactory factory = spy(
new UndertowServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void deduceUseForwardHeadersUndertow() throws Exception {
this.customizer.setEnvironment(new MockEnvironment().withProperty("DYNO", "-"));
UndertowServletWebServerFactory factory = spy(
new UndertowServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void defaultUseForwardHeadersJetty() throws Exception {
JettyServletWebServerFactory factory = spy(new JettyServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(false);
}
@Test
public void setUseForwardHeadersJetty() throws Exception {
this.properties.setUseForwardHeaders(true);
JettyServletWebServerFactory factory = spy(new JettyServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void deduceUseForwardHeadersJetty() throws Exception {
this.customizer.setEnvironment(new MockEnvironment().withProperty("DYNO", "-"));
JettyServletWebServerFactory factory = spy(new JettyServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setUseForwardHeaders(true);
}
@Test
public void sessionStoreDir() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("server.session.store-dir", "myfolder");
bindProperties(map);
JettyServletWebServerFactory factory = spy(new JettyServletWebServerFactory());
this.customizer.customize(factory);
verify(factory).setSessionStoreDir(new File("myfolder"));
}
@Test
public void jettyAccessLogCanBeEnabled() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory(0);
Map<String, String> map = new HashMap<>();
map.put("server.jetty.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer();
try {
NCSARequestLog requestLog = getNCSARequestLog(webServer);
assertThat(requestLog.getFilename()).isNull();
assertThat(requestLog.isAppend()).isFalse();
assertThat(requestLog.isExtended()).isFalse();
assertThat(requestLog.getLogCookies()).isFalse();
assertThat(requestLog.getLogServer()).isFalse();
assertThat(requestLog.getLogLatency()).isFalse();
}
finally {
webServer.stop();
}
}
@Test
public void jettyAccessLogCanBeCustomized() throws IOException {
File logFile = File.createTempFile("jetty_log", ".log");
JettyServletWebServerFactory factory = new JettyServletWebServerFactory(0);
Map<String, String> map = new HashMap<>();
String timezone = TimeZone.getDefault().getID();
map.put("server.jetty.accesslog.enabled", "true");
map.put("server.jetty.accesslog.filename", logFile.getAbsolutePath());
map.put("server.jetty.accesslog.file-date-format", "yyyy-MM-dd");
map.put("server.jetty.accesslog.retention-period", "42");
map.put("server.jetty.accesslog.append", "true");
map.put("server.jetty.accesslog.extended-format", "true");
map.put("server.jetty.accesslog.date-format", "HH:mm:ss");
map.put("server.jetty.accesslog.locale", "en_BE");
map.put("server.jetty.accesslog.time-zone", timezone);
map.put("server.jetty.accesslog.log-cookies", "true");
map.put("server.jetty.accesslog.log-server", "true");
map.put("server.jetty.accesslog.log-latency", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer();
NCSARequestLog requestLog = getNCSARequestLog(webServer);
try {
assertThat(requestLog.getFilename()).isEqualTo(logFile.getAbsolutePath());
assertThat(requestLog.getFilenameDateFormat()).isEqualTo("yyyy-MM-dd");
assertThat(requestLog.getRetainDays()).isEqualTo(42);
assertThat(requestLog.isAppend()).isTrue();
assertThat(requestLog.isExtended()).isTrue();
assertThat(requestLog.getLogDateFormat()).isEqualTo("HH:mm:ss");
assertThat(requestLog.getLogLocale()).isEqualTo(new Locale("en", "BE"));
assertThat(requestLog.getLogTimeZone()).isEqualTo(timezone);
assertThat(requestLog.getLogCookies()).isTrue();
assertThat(requestLog.getLogServer()).isTrue();
assertThat(requestLog.getLogLatency()).isTrue();
}
finally {
webServer.stop();
}
}
private NCSARequestLog getNCSARequestLog(JettyWebServer webServer) {
RequestLog requestLog = webServer.getServer().getRequestLog();
assertThat(requestLog).isInstanceOf(NCSARequestLog.class);
return (NCSARequestLog) requestLog;
}
@Test
public void skipNullElementsForUndertow() throws Exception {
UndertowServletWebServerFactory factory = mock(
UndertowServletWebServerFactory.class);
this.customizer.customize(factory);
verify(factory, never()).setAccessLogEnabled(anyBoolean());
}
private void triggerInitializers(ConfigurableServletWebServerFactory factory,
ServletContext servletContext) throws ServletException {
verify(factory, atLeastOnce()).addInitializers(this.initializersCaptor.capture());
for (Object initializers : this.initializersCaptor.getAllValues()) {
if (initializers instanceof ServletContextInitializer) {
((ServletContextInitializer) initializers).onStartup(servletContext);
}
else {
for (ServletContextInitializer initializer : (ServletContextInitializer[]) initializers) {
initializer.onStartup(servletContext);
}
}
}
}
private void bindProperties(Map<String, String> map) {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
map.forEach(source::put);
new Binder(source).bind("server", Bindable.ofInstance(this.properties));
}
}