From a6e4744c607b72435a0063d885b7208bc31481ff Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 18 Nov 2014 15:43:39 -0800 Subject: [PATCH] Fixup line endings --- .../spring-boot-starter-undertow/pom.xml | 82 +- .../META-INF/MANIFEST.MF | 6 +- .../UndertowEmbeddedServletContainer.java | 212 ++-- ...dertowEmbeddedServletContainerFactory.java | 1014 ++++++++--------- ...wEmbeddedServletContainerFactoryTests.java | 192 ++-- 5 files changed, 753 insertions(+), 753 deletions(-) diff --git a/spring-boot-starters/spring-boot-starter-undertow/pom.xml b/spring-boot-starters/spring-boot-starter-undertow/pom.xml index 72f49cc8e16..dbfc7f0ac0d 100644 --- a/spring-boot-starters/spring-boot-starter-undertow/pom.xml +++ b/spring-boot-starters/spring-boot-starter-undertow/pom.xml @@ -1,41 +1,41 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starters - 1.2.0.BUILD-SNAPSHOT - - spring-boot-starter-undertow - Spring Boot Undertow Starter - Spring Boot Undertow Starter - http://projects.spring.io/spring-boot/ - - Pivotal Software, Inc. - http://www.spring.io - - - ${basedir}/../.. - - - - io.undertow - undertow-core - - - io.undertow - undertow-servlet - - - org.jboss.spec.javax.servlet - jboss-servlet-api_3.1_spec - - - - - javax.servlet - javax.servlet-api - - - + + + 4.0.0 + + org.springframework.boot + spring-boot-starters + 1.2.0.BUILD-SNAPSHOT + + spring-boot-starter-undertow + Spring Boot Undertow Starter + Spring Boot Undertow Starter + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + io.undertow + undertow-core + + + io.undertow + undertow-servlet + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.1_spec + + + + + javax.servlet + javax.servlet-api + + + diff --git a/spring-boot-starters/spring-boot-starter-web/META-INF/MANIFEST.MF b/spring-boot-starters/spring-boot-starter-web/META-INF/MANIFEST.MF index 5e9495128c0..254272e1c07 100644 --- a/spring-boot-starters/spring-boot-starter-web/META-INF/MANIFEST.MF +++ b/spring-boot-starters/spring-boot-starter-web/META-INF/MANIFEST.MF @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -Class-Path: - +Manifest-Version: 1.0 +Class-Path: + diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java index dfe4b99f13f..7e7e8cee227 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java @@ -1,107 +1,107 @@ -/* - * Copyright 2012-2014 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.context.embedded.undertow; - -import io.undertow.Handlers; -import io.undertow.Undertow; -import io.undertow.Undertow.Builder; -import io.undertow.server.HttpHandler; -import io.undertow.server.handlers.PathHandler; -import io.undertow.servlet.api.DeploymentManager; - -import javax.servlet.ServletException; - -import org.springframework.boot.context.embedded.EmbeddedServletContainer; -import org.springframework.boot.context.embedded.EmbeddedServletContainerException; -import org.springframework.util.StringUtils; - -/** - * {@link EmbeddedServletContainer} that can be used to control an embedded Undertow - * server. Typically this class should be created using - * {@link UndertowEmbeddedServletContainerFactory} and not directly. - * - * @author Ivan Sopov - * @author Andy Wilkinson - * @since 1.2.0 - * @see UndertowEmbeddedServletContainer - */ -public class UndertowEmbeddedServletContainer implements EmbeddedServletContainer { - - private final DeploymentManager manager; - - private final Builder builder; - - private final String contextPath; - - private final int port; - - private final boolean autoStart; - - private Undertow undertow; - - private boolean started = false; - - public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager, - String contextPath, int port, boolean autoStart) { - this.builder = builder; - this.manager = manager; - this.contextPath = contextPath; - this.port = port; - this.autoStart = autoStart; - } - - @Override - public synchronized void start() throws EmbeddedServletContainerException { - if (!this.autoStart) { - return; - } - if (this.undertow == null) { - try { - HttpHandler servletHandler = this.manager.start(); - if (StringUtils.isEmpty(this.contextPath)) { - this.builder.setHandler(servletHandler); - } - else { - PathHandler pathHandler = Handlers.path().addPrefixPath( - this.contextPath, servletHandler); - this.builder.setHandler(pathHandler); - } - this.undertow = this.builder.build(); - } - catch (ServletException ex) { - throw new EmbeddedServletContainerException( - "Unable to start embdedded Undertow", ex); - } - } - this.undertow.start(); - this.started = true; - } - - @Override - public synchronized void stop() throws EmbeddedServletContainerException { - if (this.started) { - this.started = false; - this.undertow.stop(); - } - } - - @Override - public int getPort() { - return this.port; - } - +/* + * Copyright 2012-2014 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.context.embedded.undertow; + +import io.undertow.Handlers; +import io.undertow.Undertow; +import io.undertow.Undertow.Builder; +import io.undertow.server.HttpHandler; +import io.undertow.server.handlers.PathHandler; +import io.undertow.servlet.api.DeploymentManager; + +import javax.servlet.ServletException; + +import org.springframework.boot.context.embedded.EmbeddedServletContainer; +import org.springframework.boot.context.embedded.EmbeddedServletContainerException; +import org.springframework.util.StringUtils; + +/** + * {@link EmbeddedServletContainer} that can be used to control an embedded Undertow + * server. Typically this class should be created using + * {@link UndertowEmbeddedServletContainerFactory} and not directly. + * + * @author Ivan Sopov + * @author Andy Wilkinson + * @since 1.2.0 + * @see UndertowEmbeddedServletContainer + */ +public class UndertowEmbeddedServletContainer implements EmbeddedServletContainer { + + private final DeploymentManager manager; + + private final Builder builder; + + private final String contextPath; + + private final int port; + + private final boolean autoStart; + + private Undertow undertow; + + private boolean started = false; + + public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager, + String contextPath, int port, boolean autoStart) { + this.builder = builder; + this.manager = manager; + this.contextPath = contextPath; + this.port = port; + this.autoStart = autoStart; + } + + @Override + public synchronized void start() throws EmbeddedServletContainerException { + if (!this.autoStart) { + return; + } + if (this.undertow == null) { + try { + HttpHandler servletHandler = this.manager.start(); + if (StringUtils.isEmpty(this.contextPath)) { + this.builder.setHandler(servletHandler); + } + else { + PathHandler pathHandler = Handlers.path().addPrefixPath( + this.contextPath, servletHandler); + this.builder.setHandler(pathHandler); + } + this.undertow = this.builder.build(); + } + catch (ServletException ex) { + throw new EmbeddedServletContainerException( + "Unable to start embdedded Undertow", ex); + } + } + this.undertow.start(); + this.started = true; + } + + @Override + public synchronized void stop() throws EmbeddedServletContainerException { + if (this.started) { + this.started = false; + this.undertow.stop(); + } + } + + @Override + public int getPort() { + return this.port; + } + } \ No newline at end of file diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java index d3b471a994c..6231994a015 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java @@ -1,507 +1,507 @@ -/* - * Copyright 2012-2014 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.context.embedded.undertow; - -import io.undertow.Undertow; -import io.undertow.Undertow.Builder; -import io.undertow.UndertowMessages; -import io.undertow.server.handlers.resource.ClassPathResourceManager; -import io.undertow.server.handlers.resource.FileResourceManager; -import io.undertow.server.handlers.resource.Resource; -import io.undertow.server.handlers.resource.ResourceChangeListener; -import io.undertow.server.handlers.resource.ResourceManager; -import io.undertow.server.handlers.resource.URLResource; -import io.undertow.servlet.api.DeploymentInfo; -import io.undertow.servlet.api.DeploymentManager; -import io.undertow.servlet.api.InstanceFactory; -import io.undertow.servlet.api.InstanceHandle; -import io.undertow.servlet.api.ListenerInfo; -import io.undertow.servlet.api.MimeMapping; -import io.undertow.servlet.api.ServletStackTraces; -import io.undertow.servlet.handlers.DefaultServlet; -import io.undertow.servlet.util.ImmediateInstanceHandle; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; - -import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.EmbeddedServletContainer; -import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.ErrorPage; -import org.springframework.boot.context.embedded.MimeMappings.Mapping; -import org.springframework.boot.context.embedded.ServletContextInitializer; -import org.springframework.boot.context.embedded.Ssl; -import org.springframework.boot.context.embedded.Ssl.ClientAuth; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ResourceLoader; -import org.springframework.util.Assert; -import org.springframework.util.ResourceUtils; -import org.springframework.util.SocketUtils; - -import static io.undertow.servlet.Servlets.defaultContainer; -import static io.undertow.servlet.Servlets.deployment; -import static io.undertow.servlet.Servlets.servlet; -import static org.xnio.Options.SSL_CLIENT_AUTH_MODE; -import static org.xnio.SslClientAuthMode.NOT_REQUESTED; -import static org.xnio.SslClientAuthMode.REQUESTED; -import static org.xnio.SslClientAuthMode.REQUIRED; - -/** - * {@link EmbeddedServletContainerFactory} that can be used to create - * {@link UndertowEmbeddedServletContainer}s. - *

- * Unless explicitly configured otherwise, the factory will create containers that listen - * for HTTP requests on port 8080. - * - * @author Ivan Sopov - * @author Andy Wilkinson - * @since 1.2.0 - * @see UndertowEmbeddedServletContainer - */ -public class UndertowEmbeddedServletContainerFactory extends - AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware { - - private List undertowBuilderCustomizers = new ArrayList(); - - private ResourceLoader resourceLoader; - - private Integer bufferSize; - - private Integer buffersPerRegion; - - private Integer ioThreads; - - private Integer workerThreads; - - private Boolean directBuffers; - - /** - * Create a new {@link UndertowEmbeddedServletContainerFactory} instance. - */ - public UndertowEmbeddedServletContainerFactory() { - super(); - setRegisterJspServlet(false); - } - - /** - * Create a new {@link UndertowEmbeddedServletContainerFactory} that listens for - * requests using the specified port. - * @param port the port to listen on - */ - public UndertowEmbeddedServletContainerFactory(int port) { - super(port); - setRegisterJspServlet(false); - } - - /** - * Create a new {@link UndertowEmbeddedServletContainerFactory} with the specified - * context path and port. - * @param contextPath root the context path - * @param port the port to listen on - */ - public UndertowEmbeddedServletContainerFactory(String contextPath, int port) { - super(contextPath, port); - setRegisterJspServlet(false); - } - - /** - * Set {@link UndertowBuilderCustomizer}s that should be applied to the Undertow - * {@link Builder}. Calling this method will replace any existing customizers. - * @param undertowBuilderCustomizers the customizers to set - */ - public void setUndertowBuilderCustomizers( - Collection undertowBuilderCustomizers) { - Assert.notNull(undertowBuilderCustomizers, - "undertowBuilderCustomizers must not be null"); - this.undertowBuilderCustomizers = new ArrayList( - undertowBuilderCustomizers); - } - - /** - * Returns a mutable collection of the {@link UndertowBuilderCustomizer}s that will be - * applied to the Undertow {@link Builder} . - * @return the customizers that will be applied - */ - public Collection getUndertowBuilderCustomizers() { - return this.undertowBuilderCustomizers; - } - - /** - * Add {@link UndertowBuilderCustomizer}s that should be used to customize the - * Undertow {@link Builder}. - * @param undertowBuilderCustomizers the customizers to add - */ - public void addUndertowBuilderCustomizers( - UndertowBuilderCustomizer... undertowBuilderCustomizers) { - Assert.notNull(undertowBuilderCustomizers, - "undertowBuilderCustomizers must not be null"); - this.undertowBuilderCustomizers.addAll(Arrays.asList(undertowBuilderCustomizers)); - } - - @Override - public EmbeddedServletContainer getEmbeddedServletContainer( - ServletContextInitializer... initializers) { - DeploymentManager manager = createDeploymentManager(initializers); - - int port = getPort(); - if (port == 0) { - port = SocketUtils.findAvailableTcpPort(40000); - } - - Builder builder = createBuilder(port); - - return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(), - port, port >= 0); - } - - private Builder createBuilder(int port) { - Builder builder = Undertow.builder(); - if (this.bufferSize != null) { - builder.setBufferSize(this.bufferSize); - } - if (this.buffersPerRegion != null) { - builder.setBuffersPerRegion(this.buffersPerRegion); - } - if (this.ioThreads != null) { - builder.setIoThreads(this.ioThreads); - } - if (this.workerThreads != null) { - builder.setWorkerThreads(this.workerThreads); - } - if (this.directBuffers != null) { - builder.setDirectBuffers(this.directBuffers); - } - - if (getSsl() == null) { - builder.addHttpListener(port, "0.0.0.0"); - } - else { - configureSsl(port, builder); - } - for (UndertowBuilderCustomizer customizer : this.undertowBuilderCustomizers) { - customizer.customize(builder); - } - return builder; - } - - private void configureSsl(int port, Builder builder) { - try { - Ssl ssl = getSsl(); - SSLContext sslContext = SSLContext.getInstance(ssl.getProtocol()); - sslContext.init(getKeyManagers(), getTrustManagers(), null); - builder.addHttpsListener(port, "0.0.0.0", sslContext); - if (ssl.getClientAuth() == ClientAuth.NEED) { - builder.setSocketOption(SSL_CLIENT_AUTH_MODE, REQUIRED); - } - else if (ssl.getClientAuth() == ClientAuth.WANT) { - builder.setSocketOption(SSL_CLIENT_AUTH_MODE, REQUESTED); - } - else { - builder.setSocketOption(SSL_CLIENT_AUTH_MODE, NOT_REQUESTED); - } - } - catch (NoSuchAlgorithmException ex) { - throw new RuntimeException(ex); - } - catch (KeyManagementException ex) { - throw new RuntimeException(ex); - } - } - - private KeyManager[] getKeyManagers() { - try { - Ssl ssl = getSsl(); - - String keyStoreType = ssl.getKeyStoreType(); - if (keyStoreType == null) { - keyStoreType = "JKS"; - } - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - URL url = ResourceUtils.getURL(ssl.getKeyStore()); - keyStore.load(url.openStream(), ssl.getKeyStorePassword().toCharArray()); - - // Get key manager to provide client credentials. - KeyManagerFactory keyManagerFactory = KeyManagerFactory - .getInstance(KeyManagerFactory.getDefaultAlgorithm()); - char[] keyPassword = ssl.getKeyPassword() != null ? ssl.getKeyPassword() - .toCharArray() : ssl.getKeyStorePassword().toCharArray(); - keyManagerFactory.init(keyStore, keyPassword); - return keyManagerFactory.getKeyManagers(); - } - catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private TrustManager[] getTrustManagers() { - try { - Ssl ssl = getSsl(); - - String trustStoreType = ssl.getTrustStoreType(); - if (trustStoreType == null) { - trustStoreType = "JKS"; - } - String trustStore = ssl.getTrustStore(); - if (trustStore == null) { - return null; - } - KeyStore trustedKeyStore = KeyStore.getInstance(trustStoreType); - URL url = ResourceUtils.getURL(trustStore); - trustedKeyStore.load(url.openStream(), ssl.getTrustStorePassword() - .toCharArray()); - - TrustManagerFactory trustManagerFactory = TrustManagerFactory - .getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(trustedKeyStore); - return trustManagerFactory.getTrustManagers(); - } - catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private DeploymentManager createDeploymentManager( - ServletContextInitializer... initializers) { - DeploymentInfo servletBuilder = deployment(); - - servletBuilder.addListener(new ListenerInfo( - UndertowSpringServletContextListener.class, - new UndertowSpringServletContextListenerFactory( - new UndertowSpringServletContextListener( - mergeInitializers(initializers))))); - - if (this.resourceLoader != null) { - servletBuilder.setClassLoader(this.resourceLoader.getClassLoader()); - } - else { - servletBuilder.setClassLoader(getClass().getClassLoader()); - } - servletBuilder.setContextPath(getContextPath()); - servletBuilder.setDeploymentName("spring-boot"); - if (isRegisterDefaultServlet()) { - servletBuilder.addServlet(servlet("default", DefaultServlet.class)); - } - - configureErrorPages(servletBuilder); - servletBuilder.setServletStackTraces(ServletStackTraces.NONE); - - File root = getValidDocumentRoot(); - if (root != null && root.isDirectory()) { - servletBuilder.setResourceManager(new FileResourceManager(root, 0)); - } - else if (root != null && root.isFile()) { - servletBuilder.setResourceManager(new JarResourcemanager(root)); - } - else if (this.resourceLoader != null) { - servletBuilder.setResourceManager(new ClassPathResourceManager( - this.resourceLoader.getClassLoader(), "")); - } - else { - servletBuilder.setResourceManager(new ClassPathResourceManager(getClass() - .getClassLoader(), "")); - } - for (Mapping mimeMapping : getMimeMappings()) { - servletBuilder.addMimeMapping(new MimeMapping(mimeMapping.getExtension(), - mimeMapping.getMimeType())); - } - - DeploymentManager manager = defaultContainer().addDeployment(servletBuilder); - - manager.deploy(); - - manager.getDeployment().getSessionManager() - .setDefaultSessionTimeout(getSessionTimeout()); - return manager; - } - - private void configureErrorPages(DeploymentInfo servletBuilder) { - for (ErrorPage errorPage : getErrorPages()) { - if (errorPage.getStatus() != null) { - io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( - errorPage.getPath(), errorPage.getStatusCode()); - servletBuilder.addErrorPage(undertowErrorpage); - } - else if (errorPage.getException() != null) { - io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( - errorPage.getPath(), errorPage.getException()); - servletBuilder.addErrorPage(undertowErrorpage); - } - else { - io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( - errorPage.getPath()); - servletBuilder.addErrorPage(undertowErrorpage); - } - } - } - - /** - * Factory method called to create the {@link UndertowEmbeddedServletContainer}. - * Subclasses can override this method to return a different - * {@link UndertowEmbeddedServletContainer} or apply additional processing to the - * {@link Builder} and {@link DeploymentManager} used to bootstrap Undertow - * - * @param builder the builder - * @param manager the deployment manager - * @param port the port that Undertow should listen on - * @return a new {@link UndertowEmbeddedServletContainer} instance - */ - protected UndertowEmbeddedServletContainer getUndertowEmbeddedServletContainer( - Builder builder, DeploymentManager manager, int port) { - return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(), - port, port >= 0); - } - - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - public void setBufferSize(Integer bufferSize) { - this.bufferSize = bufferSize; - } - - public void setBuffersPerRegion(Integer buffersPerRegion) { - this.buffersPerRegion = buffersPerRegion; - } - - public void setIoThreads(Integer ioThreads) { - this.ioThreads = ioThreads; - } - - public void setWorkerThreads(Integer workerThreads) { - this.workerThreads = workerThreads; - } - - public void setDirectBuffers(Boolean directBuffers) { - this.directBuffers = directBuffers; - } - - @Override - public void setRegisterJspServlet(boolean registerJspServlet) { - Assert.isTrue(!registerJspServlet, "Undertow does not support JSPs"); - super.setRegisterJspServlet(registerJspServlet); - } - - private static class JarResourcemanager implements ResourceManager { - private final String jarPath; - - public JarResourcemanager(File jarFile) { - this(jarFile.getAbsolutePath()); - } - - public JarResourcemanager(String jarPath) { - this.jarPath = jarPath; - } - - @Override - public void close() throws IOException { - // no code - } - - @Override - public Resource getResource(String path) throws IOException { - URL url = new URL("jar:file:" + this.jarPath + "!" + path); - URLResource resource = new URLResource(url, url.openConnection(), path); - if (resource.getContentLength() < 0) { - return null; - } - return resource; - } - - @Override - public boolean isResourceChangeListenerSupported() { - return false; - } - - @Override - public void registerResourceChangeListener(ResourceChangeListener listener) { - throw UndertowMessages.MESSAGES.resourceChangeListenerNotSupported(); - - } - - @Override - public void removeResourceChangeListener(ResourceChangeListener listener) { - throw UndertowMessages.MESSAGES.resourceChangeListenerNotSupported(); - - } - - } - - private static class UndertowSpringServletContextListenerFactory implements - InstanceFactory { - - private final UndertowSpringServletContextListener listener; - - public UndertowSpringServletContextListenerFactory( - UndertowSpringServletContextListener listener) { - this.listener = listener; - } - - @Override - public InstanceHandle createInstance() - throws InstantiationException { - return new ImmediateInstanceHandle( - this.listener); - } - - } - - private static class UndertowSpringServletContextListener implements - ServletContextListener { - private final ServletContextInitializer[] initializers; - - public UndertowSpringServletContextListener( - ServletContextInitializer... initializers) { - this.initializers = initializers; - } - - @Override - public void contextInitialized(ServletContextEvent event) { - try { - for (ServletContextInitializer initializer : this.initializers) { - initializer.onStartup(event.getServletContext()); - } - } - catch (ServletException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - // no code - } - } - -} +/* + * Copyright 2012-2014 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.context.embedded.undertow; + +import io.undertow.Undertow; +import io.undertow.Undertow.Builder; +import io.undertow.UndertowMessages; +import io.undertow.server.handlers.resource.ClassPathResourceManager; +import io.undertow.server.handlers.resource.FileResourceManager; +import io.undertow.server.handlers.resource.Resource; +import io.undertow.server.handlers.resource.ResourceChangeListener; +import io.undertow.server.handlers.resource.ResourceManager; +import io.undertow.server.handlers.resource.URLResource; +import io.undertow.servlet.api.DeploymentInfo; +import io.undertow.servlet.api.DeploymentManager; +import io.undertow.servlet.api.InstanceFactory; +import io.undertow.servlet.api.InstanceHandle; +import io.undertow.servlet.api.ListenerInfo; +import io.undertow.servlet.api.MimeMapping; +import io.undertow.servlet.api.ServletStackTraces; +import io.undertow.servlet.handlers.DefaultServlet; +import io.undertow.servlet.util.ImmediateInstanceHandle; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; + +import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.EmbeddedServletContainer; +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.ErrorPage; +import org.springframework.boot.context.embedded.MimeMappings.Mapping; +import org.springframework.boot.context.embedded.ServletContextInitializer; +import org.springframework.boot.context.embedded.Ssl; +import org.springframework.boot.context.embedded.Ssl.ClientAuth; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.Assert; +import org.springframework.util.ResourceUtils; +import org.springframework.util.SocketUtils; + +import static io.undertow.servlet.Servlets.defaultContainer; +import static io.undertow.servlet.Servlets.deployment; +import static io.undertow.servlet.Servlets.servlet; +import static org.xnio.Options.SSL_CLIENT_AUTH_MODE; +import static org.xnio.SslClientAuthMode.NOT_REQUESTED; +import static org.xnio.SslClientAuthMode.REQUESTED; +import static org.xnio.SslClientAuthMode.REQUIRED; + +/** + * {@link EmbeddedServletContainerFactory} that can be used to create + * {@link UndertowEmbeddedServletContainer}s. + *

+ * Unless explicitly configured otherwise, the factory will create containers that listen + * for HTTP requests on port 8080. + * + * @author Ivan Sopov + * @author Andy Wilkinson + * @since 1.2.0 + * @see UndertowEmbeddedServletContainer + */ +public class UndertowEmbeddedServletContainerFactory extends + AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware { + + private List undertowBuilderCustomizers = new ArrayList(); + + private ResourceLoader resourceLoader; + + private Integer bufferSize; + + private Integer buffersPerRegion; + + private Integer ioThreads; + + private Integer workerThreads; + + private Boolean directBuffers; + + /** + * Create a new {@link UndertowEmbeddedServletContainerFactory} instance. + */ + public UndertowEmbeddedServletContainerFactory() { + super(); + setRegisterJspServlet(false); + } + + /** + * Create a new {@link UndertowEmbeddedServletContainerFactory} that listens for + * requests using the specified port. + * @param port the port to listen on + */ + public UndertowEmbeddedServletContainerFactory(int port) { + super(port); + setRegisterJspServlet(false); + } + + /** + * Create a new {@link UndertowEmbeddedServletContainerFactory} with the specified + * context path and port. + * @param contextPath root the context path + * @param port the port to listen on + */ + public UndertowEmbeddedServletContainerFactory(String contextPath, int port) { + super(contextPath, port); + setRegisterJspServlet(false); + } + + /** + * Set {@link UndertowBuilderCustomizer}s that should be applied to the Undertow + * {@link Builder}. Calling this method will replace any existing customizers. + * @param undertowBuilderCustomizers the customizers to set + */ + public void setUndertowBuilderCustomizers( + Collection undertowBuilderCustomizers) { + Assert.notNull(undertowBuilderCustomizers, + "undertowBuilderCustomizers must not be null"); + this.undertowBuilderCustomizers = new ArrayList( + undertowBuilderCustomizers); + } + + /** + * Returns a mutable collection of the {@link UndertowBuilderCustomizer}s that will be + * applied to the Undertow {@link Builder} . + * @return the customizers that will be applied + */ + public Collection getUndertowBuilderCustomizers() { + return this.undertowBuilderCustomizers; + } + + /** + * Add {@link UndertowBuilderCustomizer}s that should be used to customize the + * Undertow {@link Builder}. + * @param undertowBuilderCustomizers the customizers to add + */ + public void addUndertowBuilderCustomizers( + UndertowBuilderCustomizer... undertowBuilderCustomizers) { + Assert.notNull(undertowBuilderCustomizers, + "undertowBuilderCustomizers must not be null"); + this.undertowBuilderCustomizers.addAll(Arrays.asList(undertowBuilderCustomizers)); + } + + @Override + public EmbeddedServletContainer getEmbeddedServletContainer( + ServletContextInitializer... initializers) { + DeploymentManager manager = createDeploymentManager(initializers); + + int port = getPort(); + if (port == 0) { + port = SocketUtils.findAvailableTcpPort(40000); + } + + Builder builder = createBuilder(port); + + return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(), + port, port >= 0); + } + + private Builder createBuilder(int port) { + Builder builder = Undertow.builder(); + if (this.bufferSize != null) { + builder.setBufferSize(this.bufferSize); + } + if (this.buffersPerRegion != null) { + builder.setBuffersPerRegion(this.buffersPerRegion); + } + if (this.ioThreads != null) { + builder.setIoThreads(this.ioThreads); + } + if (this.workerThreads != null) { + builder.setWorkerThreads(this.workerThreads); + } + if (this.directBuffers != null) { + builder.setDirectBuffers(this.directBuffers); + } + + if (getSsl() == null) { + builder.addHttpListener(port, "0.0.0.0"); + } + else { + configureSsl(port, builder); + } + for (UndertowBuilderCustomizer customizer : this.undertowBuilderCustomizers) { + customizer.customize(builder); + } + return builder; + } + + private void configureSsl(int port, Builder builder) { + try { + Ssl ssl = getSsl(); + SSLContext sslContext = SSLContext.getInstance(ssl.getProtocol()); + sslContext.init(getKeyManagers(), getTrustManagers(), null); + builder.addHttpsListener(port, "0.0.0.0", sslContext); + if (ssl.getClientAuth() == ClientAuth.NEED) { + builder.setSocketOption(SSL_CLIENT_AUTH_MODE, REQUIRED); + } + else if (ssl.getClientAuth() == ClientAuth.WANT) { + builder.setSocketOption(SSL_CLIENT_AUTH_MODE, REQUESTED); + } + else { + builder.setSocketOption(SSL_CLIENT_AUTH_MODE, NOT_REQUESTED); + } + } + catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } + } + + private KeyManager[] getKeyManagers() { + try { + Ssl ssl = getSsl(); + + String keyStoreType = ssl.getKeyStoreType(); + if (keyStoreType == null) { + keyStoreType = "JKS"; + } + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + URL url = ResourceUtils.getURL(ssl.getKeyStore()); + keyStore.load(url.openStream(), ssl.getKeyStorePassword().toCharArray()); + + // Get key manager to provide client credentials. + KeyManagerFactory keyManagerFactory = KeyManagerFactory + .getInstance(KeyManagerFactory.getDefaultAlgorithm()); + char[] keyPassword = ssl.getKeyPassword() != null ? ssl.getKeyPassword() + .toCharArray() : ssl.getKeyStorePassword().toCharArray(); + keyManagerFactory.init(keyStore, keyPassword); + return keyManagerFactory.getKeyManagers(); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + private TrustManager[] getTrustManagers() { + try { + Ssl ssl = getSsl(); + + String trustStoreType = ssl.getTrustStoreType(); + if (trustStoreType == null) { + trustStoreType = "JKS"; + } + String trustStore = ssl.getTrustStore(); + if (trustStore == null) { + return null; + } + KeyStore trustedKeyStore = KeyStore.getInstance(trustStoreType); + URL url = ResourceUtils.getURL(trustStore); + trustedKeyStore.load(url.openStream(), ssl.getTrustStorePassword() + .toCharArray()); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustedKeyStore); + return trustManagerFactory.getTrustManagers(); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + private DeploymentManager createDeploymentManager( + ServletContextInitializer... initializers) { + DeploymentInfo servletBuilder = deployment(); + + servletBuilder.addListener(new ListenerInfo( + UndertowSpringServletContextListener.class, + new UndertowSpringServletContextListenerFactory( + new UndertowSpringServletContextListener( + mergeInitializers(initializers))))); + + if (this.resourceLoader != null) { + servletBuilder.setClassLoader(this.resourceLoader.getClassLoader()); + } + else { + servletBuilder.setClassLoader(getClass().getClassLoader()); + } + servletBuilder.setContextPath(getContextPath()); + servletBuilder.setDeploymentName("spring-boot"); + if (isRegisterDefaultServlet()) { + servletBuilder.addServlet(servlet("default", DefaultServlet.class)); + } + + configureErrorPages(servletBuilder); + servletBuilder.setServletStackTraces(ServletStackTraces.NONE); + + File root = getValidDocumentRoot(); + if (root != null && root.isDirectory()) { + servletBuilder.setResourceManager(new FileResourceManager(root, 0)); + } + else if (root != null && root.isFile()) { + servletBuilder.setResourceManager(new JarResourcemanager(root)); + } + else if (this.resourceLoader != null) { + servletBuilder.setResourceManager(new ClassPathResourceManager( + this.resourceLoader.getClassLoader(), "")); + } + else { + servletBuilder.setResourceManager(new ClassPathResourceManager(getClass() + .getClassLoader(), "")); + } + for (Mapping mimeMapping : getMimeMappings()) { + servletBuilder.addMimeMapping(new MimeMapping(mimeMapping.getExtension(), + mimeMapping.getMimeType())); + } + + DeploymentManager manager = defaultContainer().addDeployment(servletBuilder); + + manager.deploy(); + + manager.getDeployment().getSessionManager() + .setDefaultSessionTimeout(getSessionTimeout()); + return manager; + } + + private void configureErrorPages(DeploymentInfo servletBuilder) { + for (ErrorPage errorPage : getErrorPages()) { + if (errorPage.getStatus() != null) { + io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( + errorPage.getPath(), errorPage.getStatusCode()); + servletBuilder.addErrorPage(undertowErrorpage); + } + else if (errorPage.getException() != null) { + io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( + errorPage.getPath(), errorPage.getException()); + servletBuilder.addErrorPage(undertowErrorpage); + } + else { + io.undertow.servlet.api.ErrorPage undertowErrorpage = new io.undertow.servlet.api.ErrorPage( + errorPage.getPath()); + servletBuilder.addErrorPage(undertowErrorpage); + } + } + } + + /** + * Factory method called to create the {@link UndertowEmbeddedServletContainer}. + * Subclasses can override this method to return a different + * {@link UndertowEmbeddedServletContainer} or apply additional processing to the + * {@link Builder} and {@link DeploymentManager} used to bootstrap Undertow + * + * @param builder the builder + * @param manager the deployment manager + * @param port the port that Undertow should listen on + * @return a new {@link UndertowEmbeddedServletContainer} instance + */ + protected UndertowEmbeddedServletContainer getUndertowEmbeddedServletContainer( + Builder builder, DeploymentManager manager, int port) { + return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(), + port, port >= 0); + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public void setBufferSize(Integer bufferSize) { + this.bufferSize = bufferSize; + } + + public void setBuffersPerRegion(Integer buffersPerRegion) { + this.buffersPerRegion = buffersPerRegion; + } + + public void setIoThreads(Integer ioThreads) { + this.ioThreads = ioThreads; + } + + public void setWorkerThreads(Integer workerThreads) { + this.workerThreads = workerThreads; + } + + public void setDirectBuffers(Boolean directBuffers) { + this.directBuffers = directBuffers; + } + + @Override + public void setRegisterJspServlet(boolean registerJspServlet) { + Assert.isTrue(!registerJspServlet, "Undertow does not support JSPs"); + super.setRegisterJspServlet(registerJspServlet); + } + + private static class JarResourcemanager implements ResourceManager { + private final String jarPath; + + public JarResourcemanager(File jarFile) { + this(jarFile.getAbsolutePath()); + } + + public JarResourcemanager(String jarPath) { + this.jarPath = jarPath; + } + + @Override + public void close() throws IOException { + // no code + } + + @Override + public Resource getResource(String path) throws IOException { + URL url = new URL("jar:file:" + this.jarPath + "!" + path); + URLResource resource = new URLResource(url, url.openConnection(), path); + if (resource.getContentLength() < 0) { + return null; + } + return resource; + } + + @Override + public boolean isResourceChangeListenerSupported() { + return false; + } + + @Override + public void registerResourceChangeListener(ResourceChangeListener listener) { + throw UndertowMessages.MESSAGES.resourceChangeListenerNotSupported(); + + } + + @Override + public void removeResourceChangeListener(ResourceChangeListener listener) { + throw UndertowMessages.MESSAGES.resourceChangeListenerNotSupported(); + + } + + } + + private static class UndertowSpringServletContextListenerFactory implements + InstanceFactory { + + private final UndertowSpringServletContextListener listener; + + public UndertowSpringServletContextListenerFactory( + UndertowSpringServletContextListener listener) { + this.listener = listener; + } + + @Override + public InstanceHandle createInstance() + throws InstantiationException { + return new ImmediateInstanceHandle( + this.listener); + } + + } + + private static class UndertowSpringServletContextListener implements + ServletContextListener { + private final ServletContextInitializer[] initializers; + + public UndertowSpringServletContextListener( + ServletContextInitializer... initializers) { + this.initializers = initializers; + } + + @Override + public void contextInitialized(ServletContextEvent event) { + try { + for (ServletContextInitializer initializer : this.initializers) { + initializer.onStartup(event.getServletContext()); + } + } + catch (ServletException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + // no code + } + } + +} diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java index d24337e8c16..578cbb5c78c 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java @@ -1,96 +1,96 @@ -/* - * Copyright 2012-2014 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.context.embedded.undertow; - -import io.undertow.Undertow.Builder; - -import java.util.Arrays; - -import org.junit.Test; -import org.mockito.InOrder; -import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; -import org.springframework.boot.context.embedded.ErrorPage; -import org.springframework.boot.context.embedded.ExampleServlet; -import org.springframework.boot.context.embedded.ServletRegistrationBean; -import org.springframework.http.HttpStatus; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link UndertowEmbeddedServletContainerFactory} and - * {@link UndertowEmbeddedServletContainer} . - * - * @author Ivan Sopov - * @author Andy Wilkinson - */ -public class UndertowEmbeddedServletContainerFactoryTests extends - AbstractEmbeddedServletContainerFactoryTests { - - @Override - protected UndertowEmbeddedServletContainerFactory getFactory() { - return new UndertowEmbeddedServletContainerFactory(0); - } - - @Test - public void errorPage404() throws Exception { - AbstractEmbeddedServletContainerFactory factory = getFactory(); - factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/hello")); - this.container = factory.getEmbeddedServletContainer(new ServletRegistrationBean( - new ExampleServlet(), "/hello")); - this.container.start(); - assertThat(getResponse(getLocalUrl("/hello")), equalTo("Hello World")); - assertThat(getResponse(getLocalUrl("/not-found")), equalTo("Hello World")); - } - - @Test - public void setNullUndertowBuilderCustomizersThrows() { - UndertowEmbeddedServletContainerFactory factory = getFactory(); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("undertowBuilderCustomizers must not be null"); - factory.setUndertowBuilderCustomizers(null); - } - - @Test - public void addNullContextCustomizersThrows() { - UndertowEmbeddedServletContainerFactory factory = getFactory(); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("undertowBuilderCustomizers must not be null"); - factory.addUndertowBuilderCustomizers((UndertowBuilderCustomizer[]) null); - } - - @Test - public void builderCustomizers() throws Exception { - UndertowEmbeddedServletContainerFactory factory = getFactory(); - UndertowBuilderCustomizer[] customizers = new UndertowBuilderCustomizer[4]; - for (int i = 0; i < customizers.length; i++) { - customizers[i] = mock(UndertowBuilderCustomizer.class); - } - factory.setUndertowBuilderCustomizers(Arrays.asList(customizers[0], - customizers[1])); - factory.addUndertowBuilderCustomizers(customizers[2], customizers[3]); - this.container = factory.getEmbeddedServletContainer(); - InOrder ordered = inOrder((Object[]) customizers); - for (UndertowBuilderCustomizer customizer : customizers) { - ordered.verify(customizer).customize((Builder) anyObject()); - } - } -} +/* + * Copyright 2012-2014 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.context.embedded.undertow; + +import io.undertow.Undertow.Builder; + +import java.util.Arrays; + +import org.junit.Test; +import org.mockito.InOrder; +import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; +import org.springframework.boot.context.embedded.ErrorPage; +import org.springframework.boot.context.embedded.ExampleServlet; +import org.springframework.boot.context.embedded.ServletRegistrationBean; +import org.springframework.http.HttpStatus; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link UndertowEmbeddedServletContainerFactory} and + * {@link UndertowEmbeddedServletContainer} . + * + * @author Ivan Sopov + * @author Andy Wilkinson + */ +public class UndertowEmbeddedServletContainerFactoryTests extends + AbstractEmbeddedServletContainerFactoryTests { + + @Override + protected UndertowEmbeddedServletContainerFactory getFactory() { + return new UndertowEmbeddedServletContainerFactory(0); + } + + @Test + public void errorPage404() throws Exception { + AbstractEmbeddedServletContainerFactory factory = getFactory(); + factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/hello")); + this.container = factory.getEmbeddedServletContainer(new ServletRegistrationBean( + new ExampleServlet(), "/hello")); + this.container.start(); + assertThat(getResponse(getLocalUrl("/hello")), equalTo("Hello World")); + assertThat(getResponse(getLocalUrl("/not-found")), equalTo("Hello World")); + } + + @Test + public void setNullUndertowBuilderCustomizersThrows() { + UndertowEmbeddedServletContainerFactory factory = getFactory(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("undertowBuilderCustomizers must not be null"); + factory.setUndertowBuilderCustomizers(null); + } + + @Test + public void addNullContextCustomizersThrows() { + UndertowEmbeddedServletContainerFactory factory = getFactory(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("undertowBuilderCustomizers must not be null"); + factory.addUndertowBuilderCustomizers((UndertowBuilderCustomizer[]) null); + } + + @Test + public void builderCustomizers() throws Exception { + UndertowEmbeddedServletContainerFactory factory = getFactory(); + UndertowBuilderCustomizer[] customizers = new UndertowBuilderCustomizer[4]; + for (int i = 0; i < customizers.length; i++) { + customizers[i] = mock(UndertowBuilderCustomizer.class); + } + factory.setUndertowBuilderCustomizers(Arrays.asList(customizers[0], + customizers[1])); + factory.addUndertowBuilderCustomizers(customizers[2], customizers[3]); + this.container = factory.getEmbeddedServletContainer(); + InOrder ordered = inOrder((Object[]) customizers); + for (UndertowBuilderCustomizer customizer : customizers) { + ordered.verify(customizer).customize((Builder) anyObject()); + } + } +}