org.hibernate
hibernate-entitymanager
diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowBuilderCustomizer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowBuilderCustomizer.java
new file mode 100644
index 0000000000..75436d2b08
--- /dev/null
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowBuilderCustomizer.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * Callback interface that can be used to customize an Undertow {@link Builder}.
+ *
+ * @author Andy Wilkinson
+ * @since 1.2.0
+ * @see UndertowEmbeddedServletContainerFactory
+ */
+public interface UndertowBuilderCustomizer {
+
+ /**
+ * @param builder the {@code Builder} to customize
+ */
+ void customize(Builder builder);
+
+}
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
new file mode 100644
index 0000000000..dfe4b99f13
--- /dev/null
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java
@@ -0,0 +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;
+ }
+
+}
\ 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
new file mode 100644
index 0000000000..d3b471a994
--- /dev/null
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java
@@ -0,0 +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 extends UndertowBuilderCustomizer> 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/main/java/org/springframework/boot/context/embedded/undertow/package-info.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/package-info.java
new file mode 100644
index 0000000000..c0092c5f73
--- /dev/null
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for Undertow {@link org.springframework.boot.context.embedded.EmbeddedServletContainer EmbeddedServletContainers}.
+ *
+ * @see org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
+ */
+package org.springframework.boot.context.embedded.undertow;
+
diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java
index c8f9ca2969..1a7be91bf4 100644
--- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java
@@ -24,6 +24,7 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -48,6 +49,7 @@ import static org.junit.Assert.assertThat;
* {@link EmbeddedServletContainer}s running Spring MVC.
*
* @author Phillip Webb
+ * @author Ivan Sopov
*/
public class EmbeddedServletContainerMvcIntegrationTests {
@@ -76,6 +78,13 @@ public class EmbeddedServletContainerMvcIntegrationTests {
doTest(this.context, "/hello");
}
+ @Test
+ public void undertow() throws Exception {
+ this.context = new AnnotationConfigEmbeddedWebApplicationContext(
+ UndertowConfig.class);
+ doTest(this.context, "/hello");
+ }
+
@Test
public void advancedConfig() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(
@@ -118,6 +127,15 @@ public class EmbeddedServletContainerMvcIntegrationTests {
}
}
+ @Configuration
+ @Import(Config.class)
+ public static class UndertowConfig {
+ @Bean
+ public EmbeddedServletContainerFactory containerFactory() {
+ return new UndertowEmbeddedServletContainerFactory(0);
+ }
+ }
+
@Configuration
@EnableWebMvc
public static class Config {
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
new file mode 100644
index 0000000000..d24337e8c1
--- /dev/null
+++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java
@@ -0,0 +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());
+ }
+ }
+}