diff --git a/spring-boot-containers/spring-boot-tomcat8/pom.xml b/spring-boot-containers/spring-boot-tomcat8/pom.xml
deleted file mode 100644
index e386511fc39..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/pom.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-parent
- 0.5.0.BUILD-SNAPSHOT
- ../../spring-boot-parent
-
- spring-boot-tomcat8
- jar
-
- ${basedir}/../..
- 8.0.0-RC1
-
-
-
-
- ${project.groupId}
- spring-boot
- ${project.version}
-
-
-
- org.apache.tomcat.embed
- tomcat-embed-core
- ${tomcat8.version}
- true
-
-
-
-
-
-
- maven-jar-plugin
-
-
-
- test-jar
-
-
-
-
-
-
-
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/ServletContextInitializerLifecycleListener.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/ServletContextInitializerLifecycleListener.java
deleted file mode 100644
index 72c2f8d9410..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/ServletContextInitializerLifecycleListener.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2002-2013 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.tomcat8;
-
-import javax.servlet.ServletException;
-
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleEvent;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.core.StandardContext;
-import org.springframework.boot.context.embedded.ServletContextInitializer;
-import org.springframework.util.Assert;
-
-/**
- * Tomcat {@link LifecycleListener} that calls {@link ServletContextInitializer}s.
- *
- * @author Phillip Webb
- */
-public class ServletContextInitializerLifecycleListener implements LifecycleListener {
-
- private ServletContextInitializer[] initializers;
-
- /**
- * Create a new {@link ServletContextInitializerLifecycleListener} instance with the
- * specified initializers.
- * @param initializers the initializers to call
- */
- public ServletContextInitializerLifecycleListener(
- ServletContextInitializer... initializers) {
- this.initializers = initializers;
- }
-
- @Override
- public void lifecycleEvent(LifecycleEvent event) {
- if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) {
- Assert.isInstanceOf(StandardContext.class, event.getSource());
- StandardContext standardContext = (StandardContext) event.getSource();
- for (ServletContextInitializer initializer : this.initializers) {
- try {
- initializer.onStartup(standardContext.getServletContext());
- }
- catch (ServletException ex) {
- throw new IllegalStateException(ex);
- }
- }
- }
- }
-
-}
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatContextCustomizer.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatContextCustomizer.java
deleted file mode 100644
index f7a7ebc3939..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatContextCustomizer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2012-2013 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.tomcat8;
-
-import org.apache.catalina.Context;
-
-/**
- * @author Dave Syer
- */
-public interface TomcatContextCustomizer {
-
- /**
- * @param context the context to customize
- */
- void customize(Context context);
-
-}
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainer.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainer.java
deleted file mode 100644
index 6b8b5a5052e..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainer.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2002-2013 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.tomcat8;
-
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.boot.context.embedded.EmbeddedServletContainer;
-import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
-import org.springframework.util.Assert;
-
-/**
- * {@link EmbeddedServletContainer} that can be used to control an embedded Tomcat server.
- * Usually this class should be created using the
- * {@link TomcatEmbeddedServletContainerFactory} and not directly.
- *
- * @author Phillip Webb
- * @author Dave Syer
- * @see TomcatEmbeddedServletContainerFactory
- */
-public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer {
-
- private final Log logger = LogFactory.getLog(TomcatEmbeddedServletContainer.class);
-
- private static int containerCounter = 0;
-
- private final Tomcat tomcat;
-
- /**
- * Create a new {@link TomcatEmbeddedServletContainer} instance.
- * @param tomcat the underlying Tomcat server
- */
- public TomcatEmbeddedServletContainer(Tomcat tomcat) {
- Assert.notNull(tomcat, "Tomcat Server must not be null");
- this.tomcat = tomcat;
- initialize();
- }
-
- private synchronized void initialize() throws EmbeddedServletContainerException {
- try {
- this.tomcat.start();
- // Unlike Jetty, all Tomcat threads are daemon threads. We create a
- // blocking non-daemon to stop immediate shutdown
- Thread awaitThread = new Thread("container-" + (containerCounter++)) {
- @Override
- public void run() {
- TomcatEmbeddedServletContainer.this.tomcat.getServer().await();
- };
- };
- awaitThread.setDaemon(false);
- awaitThread.start();
- }
- catch (Exception ex) {
- throw new EmbeddedServletContainerException(
- "Unable to start embdedded Tomcat", ex);
- }
- }
-
- @Override
- public void start() throws EmbeddedServletContainerException {
- Connector connector = this.tomcat.getConnector();
- if (connector != null) {
- try {
- connector.getProtocolHandler().resume();
- }
- catch (Exception e) {
- this.logger.error("Cannot start connector: ", e);
- }
- }
- }
-
- @Override
- public synchronized void stop() throws EmbeddedServletContainerException {
- try {
- try {
- this.tomcat.stop();
- }
- catch (LifecycleException ex) {
- // swallow and continue
- }
- this.tomcat.destroy();
- }
- catch (Exception ex) {
- throw new EmbeddedServletContainerException(
- "Unable to stop embdedded Tomcat", ex);
- }
- }
-
- /**
- * Returns access to the underlying Tomcat server.
- */
- public Tomcat getTomcat() {
- return this.tomcat;
- }
-
-}
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainerFactory.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainerFactory.java
deleted file mode 100644
index 3bb0bb0a04c..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedServletContainerFactory.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2002-2013 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.tomcat8;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.Host;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.Valve;
-import org.apache.catalina.Wrapper;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.loader.WebappLoader;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.catalina.startup.Tomcat.FixContextListener;
-import org.apache.coyote.AbstractProtocol;
-import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
-import org.springframework.boot.context.embedded.EmbeddedServletContainer;
-import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
-import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
-import org.springframework.boot.context.embedded.ErrorPage;
-import org.springframework.boot.context.embedded.MimeMappings;
-import org.springframework.boot.context.embedded.ServletContextInitializer;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-
-/**
- * {@link EmbeddedServletContainerFactory} that can be used to create
- * {@link TomcatEmbeddedServletContainer}s. Can be initialized using Spring's
- * {@link ServletContextInitializer}s or Tomcat {@link LifecycleListener}s.
- *
- *
- * Unless explicitly configured otherwise this factory will created containers that
- * listens for HTTP requests on port 8080.
- *
- * @author Phillip Webb
- * @author Dave Syer
- * @see #setPort(int)
- * @see #setContextLifecycleListeners(Collection)
- * @see TomcatEmbeddedServletContainer
- */
-public class TomcatEmbeddedServletContainerFactory extends
- AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware {
-
- private static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
-
- private File baseDirectory;
-
- private List contextValves = new ArrayList();
-
- private List contextLifecycleListeners = new ArrayList();
-
- private List tomcatContextCustomizers = new ArrayList();
-
- private ResourceLoader resourceLoader;
-
- private String protocol = DEFAULT_PROTOCOL;
-
- /**
- * Create a new {@link TomcatEmbeddedServletContainerFactory} instance.
- */
- public TomcatEmbeddedServletContainerFactory() {
- super();
- }
-
- /**
- * Create a new {@link TomcatEmbeddedServletContainerFactory} that listens for
- * requests using the specified port.
- * @param port the port to listen on
- */
- public TomcatEmbeddedServletContainerFactory(int port) {
- super(port);
- }
-
- /**
- * Create a new {@link TomcatEmbeddedServletContainerFactory} with the specified
- * context path and port.
- * @param contextPath root the context path
- * @param port the port to listen on
- */
- public TomcatEmbeddedServletContainerFactory(String contextPath, int port) {
- super(contextPath, port);
- }
-
- @Override
- public EmbeddedServletContainer getEmbeddedServletContainer(
- ServletContextInitializer... initializers) {
-
- Connector connector;
- Tomcat tomcat = new Tomcat();
-
- if (getPort() == 0) {
- return EmbeddedServletContainer.NONE;
- }
- File baseDir = (this.baseDirectory != null ? this.baseDirectory
- : createTempDir("tomcat"));
- tomcat.setBaseDir(baseDir.getAbsolutePath());
- connector = new Connector(this.protocol);
- customizeConnector(connector);
- tomcat.getService().addConnector(connector);
- tomcat.setConnector(connector);
- try {
- // Allow the server to start so the ServletContext is available, but stop the
- // connector to prevent requests from being handled before the Spring context
- // is ready:
- connector.getProtocolHandler().pause();
- }
- catch (Exception e) {
- this.logger.error("Cannot pause connector: ", e);
- }
- tomcat.getHost().setAutoDeploy(false);
- tomcat.getEngine().setBackgroundProcessorDelay(-1);
-
- prepareContext(tomcat.getHost(), initializers);
- return getTomcatEmbeddedServletContainer(tomcat);
- }
-
- protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
- File docBase = getValidDocumentRoot();
- docBase = (docBase != null ? docBase : createTempDir("tomcat-docbase"));
- Context context = new StandardContext();
- context.setName(getContextPath());
- context.setPath(getContextPath());
- context.setDocBase(docBase.getAbsolutePath());
- context.addLifecycleListener(new FixContextListener());
- context.setParentClassLoader(this.resourceLoader != null ? this.resourceLoader
- .getClassLoader() : ClassUtils.getDefaultClassLoader());
- WebappLoader loader = new WebappLoader(context.getParentClassLoader());
- loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
- context.setLoader(loader);
- if (isRegisterDefaultServlet()) {
- addDefaultServlet(context);
- }
- if (isRegisterJspServlet()
- && ClassUtils.isPresent(getJspServletClassName(), getClass()
- .getClassLoader())) {
- addJspServlet(context);
- }
- ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
- configureContext(context, initializersToUse);
- host.addChild(context);
- postProcessContext(context);
- }
-
- private void addDefaultServlet(Context context) {
- Wrapper defaultServlet = context.createWrapper();
- defaultServlet.setName("default");
- defaultServlet.setServletClass("org.apache.catalina.servlets.DefaultServlet");
- defaultServlet.addInitParameter("debug", "0");
- defaultServlet.addInitParameter("listings", "false");
- defaultServlet.setLoadOnStartup(1);
- // Otherwise the default location of a Spring DispatcherServlet cannot be set
- defaultServlet.setOverridable(true);
- context.addChild(defaultServlet);
- context.addServletMapping("/", "default");
- }
-
- private void addJspServlet(Context context) {
- Wrapper jspServlet = context.createWrapper();
- jspServlet.setName("jsp");
- jspServlet.setServletClass(getJspServletClassName());
- jspServlet.addInitParameter("fork", "false");
- jspServlet.setLoadOnStartup(3);
- context.addChild(jspServlet);
- context.addServletMapping("*.jsp", "jsp");
- context.addServletMapping("*.jspx", "jsp");
- }
-
- // Needs to be protected so it can be used by subclasses
- protected void customizeConnector(Connector connector) {
- connector.setPort(getPort());
- if (connector.getProtocolHandler() instanceof AbstractProtocol
- && getAddress() != null) {
- ((AbstractProtocol) connector.getProtocolHandler()).setAddress(getAddress());
- }
- }
-
- /**
- * Configure the Tomcat {@link Context}.
- * @param context the Tomcat context
- * @param initializers initializers to apply
- */
- protected void configureContext(Context context,
- ServletContextInitializer[] initializers) {
- context.addLifecycleListener(new ServletContextInitializerLifecycleListener(
- initializers));
- for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {
- context.addLifecycleListener(lifecycleListener);
- }
- for (Valve valve : this.contextValves) {
- context.getPipeline().addValve(valve);
- }
- for (ErrorPage errorPage : getErrorPages()) {
- org.apache.tomcat.util.descriptor.web.ErrorPage tomcatPage = new org.apache.tomcat.util.descriptor.web.ErrorPage();
- tomcatPage.setLocation(errorPage.getPath());
- tomcatPage.setExceptionType(errorPage.getExceptionName());
- tomcatPage.setErrorCode(errorPage.getStatusCode());
- context.addErrorPage(tomcatPage);
- }
- for (MimeMappings.Mapping mapping : getMimeMappings()) {
- context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
- }
- context.setSessionTimeout(getSessionTimeout());
- for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
- customizer.customize(context);
- }
- }
-
- /**
- * Post process the Tomcat {@link Context} before it used with the Tomcat Server.
- * Subclasses can override this method to apply additional processing to the
- * {@link Context}.
- * @param context the Tomcat {@link Context}
- */
- protected void postProcessContext(Context context) {
- }
-
- /**
- * Factory method called to create the {@link TomcatEmbeddedServletContainer}.
- * Subclasses can override this method to return a different
- * {@link TomcatEmbeddedServletContainer} or apply additional processing to the Tomcat
- * server.
- * @param tomcat the Tomcat server.
- * @return a new {@link TomcatEmbeddedServletContainer} instance
- */
- protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
- Tomcat tomcat) {
- return new TomcatEmbeddedServletContainer(tomcat);
- }
-
- private File createTempDir(String prefix) {
- try {
- File tempFolder = File.createTempFile(prefix + ".", "." + getPort());
- tempFolder.delete();
- tempFolder.mkdir();
- tempFolder.deleteOnExit();
- return tempFolder;
- }
- catch (IOException ex) {
- throw new EmbeddedServletContainerException(
- "Unable to create Tomcat tempdir", ex);
- }
- }
-
- @Override
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
-
- /**
- * Set the Tomcat base directory. If not specified a temporary directory will be used.
- * @param baseDirectory the tomcat base directory
- */
- public void setBaseDirectory(File baseDirectory) {
- this.baseDirectory = baseDirectory;
- }
-
- /**
- * The Tomcat protocol to use when create the {@link Connector}.
- * @see Connector#Connector(String)
- */
- public void setProtocol(String protocol) {
- Assert.hasLength(protocol, "Protocol must not be empty");
- this.protocol = protocol;
- }
-
- /**
- * Set {@link Valve}s that should be applied to the Tomcat {@link Context}. Calling
- * this method will replace any existing listeners.
- * @param contextValves the valves to set
- */
- public void setContextValves(Collection extends Valve> contextValves) {
- Assert.notNull(contextValves, "Valves must not be null");
- this.contextValves = new ArrayList(contextValves);
- }
-
- /**
- * Returns a mutable collection of the {@link Valve}s that will be applied to the
- * Tomcat {@link Context}.
- * @return the contextValves the valves that will be applied
- */
- public Collection getValves() {
- return this.contextValves;
- }
-
- /**
- * Add {@link Valve}s that should be applied to the Tomcat {@link Context}.
- * @param contextValves the valves to add
- */
- public void addContextValves(Valve... contextValves) {
- Assert.notNull(contextValves, "Valves must not be null");
- this.contextValves.addAll(Arrays.asList(contextValves));
- }
-
- /**
- * Set {@link LifecycleListener}s that should be applied to the Tomcat {@link Context}
- * . Calling this method will replace any existing listeners.
- * @param contextLifecycleListeners the listeners to set
- */
- public void setContextLifecycleListeners(
- Collection extends LifecycleListener> contextLifecycleListeners) {
- Assert.notNull(contextLifecycleListeners,
- "ContextLifecycleListeners must not be null");
- this.contextLifecycleListeners = new ArrayList(
- contextLifecycleListeners);
- }
-
- /**
- * Returns a mutable collection of the {@link LifecycleListener}s that will be applied
- * to the Tomcat {@link Context} .
- * @return the contextLifecycleListeners the listeners that will be applied
- */
- public Collection getContextLifecycleListeners() {
- return this.contextLifecycleListeners;
- }
-
- /**
- * Add {@link LifecycleListener}s that should be added to the Tomcat {@link Context}.
- * @param contextLifecycleListeners the listeners to add
- */
- public void addContextLifecycleListeners(
- LifecycleListener... contextLifecycleListeners) {
- Assert.notNull(contextLifecycleListeners,
- "ContextLifecycleListeners must not be null");
- this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners));
- }
-
- /**
- * Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat
- * {@link Context} . Calling this method will replace any existing customizers.
- * @param tomcatContextCustomizers the customizers to set
- */
- public void setTomcatContextCustomizers(
- Collection extends TomcatContextCustomizer> tomcatContextCustomizers) {
- Assert.notNull(this.contextLifecycleListeners,
- "TomcatContextCustomizers must not be null");
- this.tomcatContextCustomizers = new ArrayList(
- tomcatContextCustomizers);
- }
-
- /**
- * Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be
- * applied to the Tomcat {@link Context} .
- * @return the tomcatContextCustomizers the listeners that will be applied
- */
- public Collection getTomcatContextCustomizers() {
- return this.tomcatContextCustomizers;
- }
-
- /**
- * Add {@link TomcatContextCustomizer}s that should be added to the Tomcat
- * {@link Context}.
- * @param tomcatContextCustomizers the customizers to add
- */
- public void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers) {
- Assert.notNull(this.tomcatContextCustomizers,
- "TomcatContextCustomizer must not be null");
- this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers));
- }
-
-}
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedWebappClassLoader.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedWebappClassLoader.java
deleted file mode 100644
index e091bc7cb2d..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/TomcatEmbeddedWebappClassLoader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.springframework.boot.context.embedded.tomcat8;
-
-/*
- * Copyright 2012-2013 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.
- */
-
-import org.apache.catalina.loader.WebappClassLoader;
-
-/**
- * Extension of Tomcat's {@link WebappClassLoader} that does not consider the
- * {@link ClassLoader#getSystemClassLoader() system classloader}. This is required to to
- * ensure that any custom context classloader is always used (as is the case with some
- * executable archives).
- *
- * @author Phillip Webb
- */
-public class TomcatEmbeddedWebappClassLoader extends WebappClassLoader {
-
- public TomcatEmbeddedWebappClassLoader() {
- super();
- }
-
- public TomcatEmbeddedWebappClassLoader(ClassLoader parent) {
- super(parent);
- }
-
- @Override
- public synchronized Class> loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
-
- Class> resultClass = null;
-
- // Check local class caches
- resultClass = (resultClass == null ? findLoadedClass0(name) : resultClass);
- resultClass = (resultClass == null ? findLoadedClass(name) : resultClass);
- if (resultClass != null) {
- return resolveIfNecessary(resultClass, resolve);
- }
-
- // Check security
- checkPackageAccess(name);
-
- // Perform the actual load
- boolean delegateLoad = (this.delegate || filter(name));
-
- if (delegateLoad) {
- resultClass = (resultClass == null ? loadFromParent(name) : resultClass);
- }
- resultClass = (resultClass == null ? findClassIgnoringNotFound(name)
- : resultClass);
- if (!delegateLoad) {
- resultClass = (resultClass == null ? loadFromParent(name) : resultClass);
- }
-
- if (resultClass == null) {
- throw new ClassNotFoundException(name);
- }
-
- return resolveIfNecessary(resultClass, resolve);
- }
-
- private Class> resolveIfNecessary(Class> resultClass, boolean resolve) {
- if (resolve) {
- resolveClass(resultClass);
- }
- return (resultClass);
- }
-
- private Class> loadFromParent(String name) {
- if (this.parent == null) {
- return null;
- }
- try {
- return Class.forName(name, false, this.parent);
- }
- catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- private Class> findClassIgnoringNotFound(String name) {
- try {
- return findClass(name);
- }
- catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- private void checkPackageAccess(String name) throws ClassNotFoundException {
- if (this.securityManager != null && name.lastIndexOf('.') >= 0) {
- try {
- this.securityManager.checkPackageAccess(name.substring(0,
- name.lastIndexOf('.')));
- }
- catch (SecurityException se) {
- throw new ClassNotFoundException("Security Violation, attempt to use "
- + "Restricted Class: " + name, se);
- }
- }
- }
-
-}
diff --git a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/package-info.java b/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/package-info.java
deleted file mode 100644
index f1a98a595f8..00000000000
--- a/spring-boot-containers/spring-boot-tomcat8/src/main/java/org/springframework/boot/context/embedded/tomcat8/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2002-2013 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 Tomcat {@link org.springframework.boot.context.embedded.EmbeddedServletContainer EmbeddedServletContainers}.
- */
-package org.springframework.boot.context.embedded.tomcat8;
-
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 8aa48721708..af55b82e013 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -273,6 +273,11 @@
spring-tx
${spring.version}
+
+ org.springframework
+ spring-websocket
+ ${spring.version}
+
org.springframework
spring-web
diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml
index b0d670ebc24..2615b09a9a4 100644
--- a/spring-boot-samples/pom.xml
+++ b/spring-boot-samples/pom.xml
@@ -26,6 +26,7 @@
spring-boot-sample-traditional
spring-boot-sample-web-static
spring-boot-sample-web-ui
+ spring-boot-sample-websocket
spring-boot-sample-xml
diff --git a/spring-boot-samples/spring-boot-sample-websocket/_om.xml b/spring-boot-samples/spring-boot-sample-websocket/pom.xml
similarity index 87%
rename from spring-boot-samples/spring-boot-sample-websocket/_om.xml
rename to spring-boot-samples/spring-boot-sample-websocket/pom.xml
index 8651ffbc395..b897c0e8784 100644
--- a/spring-boot-samples/spring-boot-sample-websocket/_om.xml
+++ b/spring-boot-samples/spring-boot-sample-websocket/pom.xml
@@ -14,7 +14,8 @@
1.7
- 8.0-SNAPSHOT
+ 8.0.0-RC1
+ 4.0.0.BUILD-SNAPSHOT
org.springframework.boot.samples.websocket.config.ApplicationConfiguration
@@ -23,7 +24,10 @@
org.springframework.boot
spring-boot-starter-websocket
- ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
diff --git a/spring-boot-samples/spring-boot-sample-websocket/src/main/java/org/springframework/boot/samples/websocket/config/SampleWebSocketsApplication.java b/spring-boot-samples/spring-boot-sample-websocket/src/main/java/org/springframework/boot/samples/websocket/config/SampleWebSocketsApplication.java
index f8f2aad3a56..6269a7e005a 100644
--- a/spring-boot-samples/spring-boot-sample-websocket/src/main/java/org/springframework/boot/samples/websocket/config/SampleWebSocketsApplication.java
+++ b/spring-boot-samples/spring-boot-sample-websocket/src/main/java/org/springframework/boot/samples/websocket/config/SampleWebSocketsApplication.java
@@ -32,7 +32,7 @@ import org.springframework.boot.samples.websocket.echo.DefaultEchoService;
import org.springframework.boot.samples.websocket.echo.EchoService;
import org.springframework.boot.samples.websocket.echo.EchoWebSocketHandler;
import org.springframework.boot.samples.websocket.snake.SnakeWebSocketHandler;
-import org.springframework.boot.web.SpringServletInitializer;
+import org.springframework.boot.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@@ -40,13 +40,13 @@ import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
+import org.springframework.web.socket.sockjs.SockJsHttpRequestHandler;
import org.springframework.web.socket.sockjs.SockJsService;
-import org.springframework.web.socket.sockjs.support.DefaultSockJsService;
-import org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler;
+import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
import org.springframework.web.socket.support.PerConnectionWebSocketHandler;
@Configuration
-public class SampleWebSocketsApplication extends SpringServletInitializer {
+public class SampleWebSocketsApplication extends SpringBootServletInitializer {
@Override
protected Class>[] getConfigClasses() {
diff --git a/spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/StandardClientApp.java b/spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/SampleWebSocketsApplicationTests.java
similarity index 70%
rename from spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/StandardClientApp.java
rename to spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/SampleWebSocketsApplicationTests.java
index 76c5dfd5130..44113d7b559 100644
--- a/spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/StandardClientApp.java
+++ b/spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/SampleWebSocketsApplicationTests.java
@@ -17,28 +17,59 @@ package org.springframework.boot.samples.websocket.echo;
import static org.junit.Assert.assertEquals;
+import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.samples.websocket.client.GreetingService;
import org.springframework.boot.samples.websocket.client.SimpleClientWebSocketHandler;
import org.springframework.boot.samples.websocket.client.SimpleGreetingService;
+import org.springframework.boot.samples.websocket.config.SampleWebSocketsApplication;
import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.endpoint.StandardWebSocketClient;
-public class StandardClientApp {
+public class SampleWebSocketsApplicationTests {
- private static Log logger = LogFactory.getLog(StandardClientApp.class);
+ private static Log logger = LogFactory.getLog(SampleWebSocketsApplicationTests.class);
private static final String WS_URI = "ws://localhost:8080/echo";
+ private static ConfigurableApplicationContext context;
+
+ @BeforeClass
+ public static void start() throws Exception {
+ Future future = Executors
+ .newSingleThreadExecutor().submit(
+ new Callable() {
+ @Override
+ public ConfigurableApplicationContext call() throws Exception {
+ return (ConfigurableApplicationContext) SpringApplication
+ .run(SampleWebSocketsApplication.class);
+ }
+ });
+ context = future.get(30, TimeUnit.SECONDS);
+ }
+
+ @AfterClass
+ public static void stop() {
+ if (context != null) {
+ context.close();
+ }
+ }
+
@Test
public void runAndWait() throws Exception {
ApplicationContext context = SpringApplication.run(ClientConfiguration.class, "--spring.main.web_environment=false");
diff --git a/spring-boot-starters/spring-boot-starter-parent/pom.xml b/spring-boot-starters/spring-boot-starter-parent/pom.xml
index 7fdba1bddf2..151dbe0bfd0 100644
--- a/spring-boot-starters/spring-boot-starter-parent/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-parent/pom.xml
@@ -2,7 +2,7 @@
+ checkout of this file, be sure to modify 'spring-boot-starter-parent/src/main/parent/pom.xml'. -->
@@ -88,6 +88,11 @@
spring-boot-starter-security
${spring.boot.version}
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+ ${spring.boot.version}
+
diff --git a/spring-boot-starters/spring-boot-starter-parent/src/main/maven/pom.xml b/spring-boot-starters/spring-boot-starter-parent/src/main/maven/pom.xml
index 90b5201ab95..6aaccd8048c 100644
--- a/spring-boot-starters/spring-boot-starter-parent/src/main/maven/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-parent/src/main/maven/pom.xml
@@ -2,7 +2,7 @@
+ checkout of this file, be sure to modify 'spring-boot-starter-parent/src/main/parent/pom.xml'. -->
@@ -88,6 +88,11 @@
spring-boot-starter-security
${spring.boot.version}
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+ ${spring.boot.version}
+
diff --git a/spring-boot-starters/spring-boot-starter-websocket/pom.xml b/spring-boot-starters/spring-boot-starter-websocket/pom.xml
index 2181209b16e..2f4121cb362 100644
--- a/spring-boot-starters/spring-boot-starter-websocket/pom.xml
+++ b/spring-boot-starters/spring-boot-starter-websocket/pom.xml
@@ -11,7 +11,7 @@
jar
${basedir}/../..
- 8.0-SNAPSHOT
+ 8.0.0-RC1
@@ -35,14 +35,13 @@
${project.groupId}
- spring-boot-up-tomcat
+ spring-boot-starter-tomcat
org.springframework
spring-websocket
- ${spring.version}
org.apache.tomcat.embed
@@ -53,16 +52,4 @@
tomcat-embed-logging-juli
-
-
- tomcat-snapshots
- https://repository.apache.org/content/repositories/snapshots
-
- true
-
-
- false
-
-
-
diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
index 867d66aa78f..dec9443e550 100644
--- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
+++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
@@ -18,6 +18,7 @@ package org.springframework.boot.context.embedded.tomcat;
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -34,6 +35,7 @@ import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.Tomcat.FixContextListener;
import org.apache.coyote.AbstractProtocol;
+import org.springframework.beans.BeanUtils;
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
@@ -45,6 +47,7 @@ import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
/**
* {@link EmbeddedServletContainerFactory} that can be used to create
@@ -213,11 +216,7 @@ public class TomcatEmbeddedServletContainerFactory extends
context.getPipeline().addValve(valve);
}
for (ErrorPage errorPage : getErrorPages()) {
- org.apache.catalina.deploy.ErrorPage tomcatPage = new org.apache.catalina.deploy.ErrorPage();
- tomcatPage.setLocation(errorPage.getPath());
- tomcatPage.setExceptionType(errorPage.getExceptionName());
- tomcatPage.setErrorCode(errorPage.getStatusCode());
- context.addErrorPage(tomcatPage);
+ new TomcatErrorPage(errorPage).addToContext(context);
}
for (MimeMappings.Mapping mapping : getMimeMappings()) {
context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
@@ -380,4 +379,67 @@ public class TomcatEmbeddedServletContainerFactory extends
this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers));
}
+ private static class TomcatErrorPage {
+
+ private String location;
+ private String exceptionType;
+ private int errorCode;
+
+ private Object nativePage;
+
+ public TomcatErrorPage(ErrorPage errorPage) {
+ this.location = errorPage.getPath();
+ this.exceptionType = errorPage.getExceptionName();
+ this.errorCode = errorPage.getStatusCode();
+ this.nativePage = createNativePage(errorPage);
+ }
+
+ private Object createNativePage(ErrorPage errorPage) {
+ Object nativePage = null;
+ try {
+ if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) {
+ nativePage = new org.apache.catalina.deploy.ErrorPage();
+ }
+ else {
+ if (ClassUtils.isPresent(
+ "org.apache.tomcat.util.descriptor.web.ErrorPage", null)) {
+ nativePage = BeanUtils.instantiate(ClassUtils.forName(
+ "org.apache.tomcat.util.descriptor.web.ErrorPage", null));
+ }
+ }
+ }
+ catch (ClassNotFoundException e) {
+ }
+ catch (LinkageError e) {
+ }
+ return nativePage;
+ }
+
+ public void addToContext(Context context) {
+ Assert.state(this.nativePage != null,
+ "Neither Tomcat 7 nor 8 detected so no native error page exists");
+ if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) {
+ org.apache.catalina.deploy.ErrorPage errorPage = (org.apache.catalina.deploy.ErrorPage) this.nativePage;
+ errorPage.setLocation(this.location);
+ errorPage.setErrorCode(this.errorCode);
+ errorPage.setExceptionType(this.exceptionType);
+ context.addErrorPage(errorPage);
+ }
+ else {
+ callMethod(this.nativePage, "setLocation", this.location, String.class);
+ callMethod(this.nativePage, "setErrorCode", this.errorCode, int.class);
+ callMethod(this.nativePage, "setExceptionType", this.exceptionType,
+ String.class);
+ callMethod(context, "addErrorPage", this.nativePage,
+ this.nativePage.getClass());
+ }
+ }
+
+ private void callMethod(Object target, String name, Object value, Class> type) {
+ Method method = ReflectionUtils.findMethod(target.getClass(), name, type);
+ ReflectionUtils.invokeMethod(method, target, value);
+ }
+
+ }
+
}