Commit b1c689b9 authored by Phillip Webb's avatar Phillip Webb

Unify WebServerFactory implementations

Unify common for from the abstract `ServletWebServerFactory` and
`ReactiveWebServerFactory` classes. Common code is now located in
`AbstractConfigurableWebServerFactory`.

Fixes gh-8631
parent 099e188f
...@@ -26,7 +26,7 @@ import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler; ...@@ -26,7 +26,7 @@ import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption; import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.servlet.server.AbstractConfigurableServletWebServerFactory; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
...@@ -106,8 +106,8 @@ class SpringBootTestContextCustomizer implements ContextCustomizer { ...@@ -106,8 +106,8 @@ class SpringBootTestContextCustomizer implements ContextCustomizer {
private boolean isSslEnabled(ApplicationContext context) { private boolean isSslEnabled(ApplicationContext context) {
try { try {
AbstractConfigurableServletWebServerFactory webServerFactory = context AbstractServletWebServerFactory webServerFactory = context
.getBean(AbstractConfigurableServletWebServerFactory.class); .getBean(AbstractServletWebServerFactory.class);
return webServerFactory.getSsl() != null return webServerFactory.getSsl() != null
&& webServerFactory.getSsl().isEnabled(); && webServerFactory.getSsl().isEnabled();
} }
......
...@@ -23,7 +23,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; ...@@ -23,7 +23,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.reactive.server.AbstractConfigurableReactiveWebServerFactory; import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
...@@ -120,9 +120,10 @@ class WebTestClientContextCustomizer implements ContextCustomizer { ...@@ -120,9 +120,10 @@ class WebTestClientContextCustomizer implements ContextCustomizer {
private boolean isSslEnabled(ApplicationContext context) { private boolean isSslEnabled(ApplicationContext context) {
try { try {
AbstractConfigurableReactiveWebServerFactory webServerFactory = context AbstractReactiveWebServerFactory webServerFactory = context
.getBean(AbstractConfigurableReactiveWebServerFactory.class); .getBean(AbstractReactiveWebServerFactory.class);
return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled(); return webServerFactory.getSsl() != null
&& webServerFactory.getSsl().isEnabled();
} }
catch (NoSuchBeanDefinitionException ex) { catch (NoSuchBeanDefinitionException ex) {
return false; return false;
......
...@@ -18,6 +18,8 @@ package org.springframework.boot.web.embedded.jetty; ...@@ -18,6 +18,8 @@ package org.springframework.boot.web.embedded.jetty;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
...@@ -41,6 +43,9 @@ import org.springframework.http.server.reactive.JettyHttpHandlerAdapter; ...@@ -41,6 +43,9 @@ import org.springframework.http.server.reactive.JettyHttpHandlerAdapter;
*/ */
public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory { public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory {
private static final Log logger = LogFactory
.getLog(JettyReactiveWebServerFactory.class);
/** /**
* The number of acceptor threads to use. * The number of acceptor threads to use.
*/ */
...@@ -85,7 +90,8 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact ...@@ -85,7 +90,8 @@ public class JettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
ServletContextHandler contextHandler = new ServletContextHandler(server, "", ServletContextHandler contextHandler = new ServletContextHandler(server, "",
false, false); false, false);
contextHandler.addServlet(servletHolder, "/"); contextHandler.addServlet(servletHolder, "/");
this.logger.info("Server initialized with port: " + port); JettyReactiveWebServerFactory.logger
.info("Server initialized with port: " + port);
return server; return server;
} }
......
...@@ -16,13 +16,7 @@ ...@@ -16,13 +16,7 @@
package org.springframework.boot.web.reactive.server; package org.springframework.boot.web.reactive.server;
import java.io.File; import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.web.server.WebServerException;
/** /**
* Abstract base class for {@link ReactiveWebServerFactory} implementations. * Abstract base class for {@link ReactiveWebServerFactory} implementations.
...@@ -30,10 +24,9 @@ import org.springframework.boot.web.server.WebServerException; ...@@ -30,10 +24,9 @@ import org.springframework.boot.web.server.WebServerException;
* @author Brian Clozel * @author Brian Clozel
* @since 2.0.0 * @since 2.0.0
*/ */
public abstract class AbstractReactiveWebServerFactory extends public abstract class AbstractReactiveWebServerFactory
AbstractConfigurableReactiveWebServerFactory implements ReactiveWebServerFactory { extends AbstractConfigurableWebServerFactory
implements ConfigurableReactiveWebServerFactory {
protected final Log logger = LogFactory.getLog(getClass());
public AbstractReactiveWebServerFactory() { public AbstractReactiveWebServerFactory() {
} }
...@@ -42,25 +35,4 @@ public abstract class AbstractReactiveWebServerFactory extends ...@@ -42,25 +35,4 @@ public abstract class AbstractReactiveWebServerFactory extends
super(port); super(port);
} }
/**
* Return the absolute temp dir for given web server.
* @param prefix server name
* @return The temp dir for given server.
*/
protected File createTempDir(String prefix) {
try {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
}
catch (IOException ex) {
throw new WebServerException(
"Unable to create tempDir. java.io.tmpdir is set to "
+ System.getProperty("java.io.tmpdir"),
ex);
}
}
} }
...@@ -19,11 +19,12 @@ package org.springframework.boot.web.reactive.server; ...@@ -19,11 +19,12 @@ package org.springframework.boot.web.reactive.server;
import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.ConfigurableWebServerFactory;
/** /**
* Interface that represents customizations to a {@link ReactiveWebServerFactory}. * Configurable {@link ReactiveWebServerFactory}.
* *
* @author Brian Clozel * @author Brian Clozel
* @since 2.0.0 * @since 2.0.0
*/ */
public interface ConfigurableReactiveWebServerFactory extends ConfigurableWebServerFactory { public interface ConfigurableReactiveWebServerFactory
extends ConfigurableWebServerFactory, ReactiveWebServerFactory {
} }
...@@ -14,34 +14,38 @@ ...@@ -14,34 +14,38 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.web.reactive.server; package org.springframework.boot.web.server;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import org.springframework.boot.web.server.Compression;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.SslStoreProvider;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Abstract base class for {@link ConfigurableReactiveWebServerFactory} implementations. * Abstract base class for {@link ConfigurableWebServerFactory} implementations.
* *
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Ivan Sopov
* @author Eddú Meléndez
* @author Brian Clozel * @author Brian Clozel
* @since 2.0.0 * @since 2.0.0
*/ */
public class AbstractConfigurableReactiveWebServerFactory public class AbstractConfigurableWebServerFactory
implements ConfigurableReactiveWebServerFactory { implements ConfigurableWebServerFactory {
private int port = 8080; private int port = 8080;
private Set<ErrorPage> errorPages = new LinkedHashSet<>();
private InetAddress address; private InetAddress address;
private Set<ErrorPage> errorPages = new LinkedHashSet<>();
private Ssl ssl; private Ssl ssl;
private SslStoreProvider sslStoreProvider; private SslStoreProvider sslStoreProvider;
...@@ -51,27 +55,35 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -51,27 +55,35 @@ public class AbstractConfigurableReactiveWebServerFactory
private String serverHeader; private String serverHeader;
/** /**
* Create a new {@link AbstractConfigurableReactiveWebServerFactory} instance. * Create a new {@link AbstractConfigurableWebServerFactory} instance.
*/ */
public AbstractConfigurableReactiveWebServerFactory() { public AbstractConfigurableWebServerFactory() {
} }
/** /**
* Create a new {@link AbstractConfigurableReactiveWebServerFactory} instance with the * Create a new {@link AbstractConfigurableWebServerFactory} instance with the
* specified port. * specified port.
* @param port the port number for the reactive web server * @param port the port number for the web server
*/ */
public AbstractConfigurableReactiveWebServerFactory(int port) { public AbstractConfigurableWebServerFactory(int port) {
this.port = port; this.port = port;
} }
/**
* The port that the web server server listens on.
* @return the port
*/
public int getPort() {
return this.port;
}
@Override @Override
public void setAddress(InetAddress address) { public void setPort(int port) {
this.address = address; this.port = port;
} }
/** /**
* Return the address that the reactive web server binds to. * Return the address that the web server binds to.
* @return the address * @return the address
*/ */
public InetAddress getAddress() { public InetAddress getAddress() {
...@@ -79,16 +91,17 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -79,16 +91,17 @@ public class AbstractConfigurableReactiveWebServerFactory
} }
@Override @Override
public void setPort(int port) { public void setAddress(InetAddress address) {
this.port = port; this.address = address;
} }
/** /**
* The port that the reactive web server listens on. * Returns a mutable set of {@link ErrorPage ErrorPages} that will be used when
* @return the port * handling exceptions.
* @return the error pages
*/ */
public int getPort() { public Set<ErrorPage> getErrorPages() {
return this.port; return this.errorPages;
} }
@Override @Override
...@@ -103,13 +116,8 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -103,13 +116,8 @@ public class AbstractConfigurableReactiveWebServerFactory
this.errorPages.addAll(Arrays.asList(errorPages)); this.errorPages.addAll(Arrays.asList(errorPages));
} }
/** public Ssl getSsl() {
* Return a mutable set of {@link ErrorPage ErrorPages} that will be used when return this.ssl;
* handling exceptions.
* @return the error pages
*/
public Set<ErrorPage> getErrorPages() {
return this.errorPages;
} }
@Override @Override
...@@ -117,8 +125,8 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -117,8 +125,8 @@ public class AbstractConfigurableReactiveWebServerFactory
this.ssl = ssl; this.ssl = ssl;
} }
public Ssl getSsl() { public SslStoreProvider getSslStoreProvider() {
return this.ssl; return this.sslStoreProvider;
} }
@Override @Override
...@@ -126,10 +134,6 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -126,10 +134,6 @@ public class AbstractConfigurableReactiveWebServerFactory
this.sslStoreProvider = sslStoreProvider; this.sslStoreProvider = sslStoreProvider;
} }
public SslStoreProvider getSslStoreProvider() {
return this.sslStoreProvider;
}
public Compression getCompression() { public Compression getCompression() {
return this.compression; return this.compression;
} }
...@@ -148,4 +152,25 @@ public class AbstractConfigurableReactiveWebServerFactory ...@@ -148,4 +152,25 @@ public class AbstractConfigurableReactiveWebServerFactory
this.serverHeader = serverHeader; this.serverHeader = serverHeader;
} }
/**
* Return the absolute temp dir for given web server.
* @param prefix server name
* @return The temp dir for given server.
*/
protected final File createTempDir(String prefix) {
try {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
}
catch (IOException ex) {
throw new WebServerException(
"Unable to create tempDir. java.io.tmpdir is set to "
+ System.getProperty("java.io.tmpdir"),
ex);
}
}
} }
...@@ -20,11 +20,12 @@ import java.net.InetAddress; ...@@ -20,11 +20,12 @@ import java.net.InetAddress;
import java.util.Set; import java.util.Set;
/** /**
* Simple interface that represents customizations to a {@link WebServerFactory}. * A configurable {@link WebServerFactory}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Brian Clozel * @author Brian Clozel
* @since 2.0.0 * @since 2.0.0
* @see ErrorPageRegistry
*/ */
public interface ConfigurableWebServerFactory public interface ConfigurableWebServerFactory
extends WebServerFactory, ErrorPageRegistry { extends WebServerFactory, ErrorPageRegistry {
......
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.web.servlet.server;
import java.io.File;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.web.server.Compression;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.MimeMappings;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.SslStoreProvider;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Abstract base class for {@link ConfigurableServletWebServerFactory} implementations.
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Ivan Sopov
* @author Eddú Meléndez
* @author Brian Clozel
* @since 2.0.0
* @see AbstractServletWebServerFactory
*/
public abstract class AbstractConfigurableServletWebServerFactory
implements ConfigurableServletWebServerFactory {
private static final int DEFAULT_SESSION_TIMEOUT = (int) TimeUnit.MINUTES
.toSeconds(30);
private String contextPath = "";
private String displayName;
private boolean registerDefaultServlet = true;
private int port = 8080;
private List<ServletContextInitializer> initializers = new ArrayList<>();
private File documentRoot;
private Set<ErrorPage> errorPages = new LinkedHashSet<>();
private MimeMappings mimeMappings = new MimeMappings(MimeMappings.DEFAULT);
private InetAddress address;
private int sessionTimeout = DEFAULT_SESSION_TIMEOUT;
private boolean persistSession;
private File sessionStoreDir;
private Ssl ssl;
private SslStoreProvider sslStoreProvider;
private Jsp jsp = new Jsp();
private Compression compression;
private String serverHeader;
private Map<Locale, Charset> localeCharsetMappings = new HashMap<>();
/**
* Create a new {@link AbstractConfigurableServletWebServerFactory} instance.
*/
public AbstractConfigurableServletWebServerFactory() {
}
/**
* Create a new {@link AbstractConfigurableServletWebServerFactory} instance with the
* specified port.
* @param port the port number for the web server
*/
public AbstractConfigurableServletWebServerFactory(int port) {
this.port = port;
}
/**
* Create a new {@link AbstractConfigurableServletWebServerFactory} instance with the
* specified context path and port.
* @param contextPath the context path for the web server
* @param port the port number for the web server
*/
public AbstractConfigurableServletWebServerFactory(String contextPath, int port) {
checkContextPath(contextPath);
this.contextPath = contextPath;
this.port = port;
}
@Override
public void setContextPath(String contextPath) {
checkContextPath(contextPath);
this.contextPath = contextPath;
}
private void checkContextPath(String contextPath) {
Assert.notNull(contextPath, "ContextPath must not be null");
if (contextPath.length() > 0) {
if ("/".equals(contextPath)) {
throw new IllegalArgumentException(
"Root ContextPath must be specified using an empty string");
}
if (!contextPath.startsWith("/") || contextPath.endsWith("/")) {
throw new IllegalArgumentException(
"ContextPath must start with '/' and not end with '/'");
}
}
}
/**
* Returns the context path for the web server. The path will start with "/" and not
* end with "/". The root context is represented by an empty string.
* @return the context path
*/
public String getContextPath() {
return this.contextPath;
}
@Override
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
@Override
public void setPort(int port) {
this.port = port;
}
/**
* The port that the web server server listens on.
* @return the port
*/
public int getPort() {
return this.port;
}
@Override
public void setAddress(InetAddress address) {
this.address = address;
}
/**
* Return the address that the web server binds to.
* @return the address
*/
public InetAddress getAddress() {
return this.address;
}
@Override
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Override
public void setSessionTimeout(int sessionTimeout, TimeUnit timeUnit) {
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.sessionTimeout = (int) timeUnit.toSeconds(sessionTimeout);
}
/**
* Return the session timeout in seconds.
* @return the timeout in seconds
*/
public int getSessionTimeout() {
return this.sessionTimeout;
}
@Override
public void setPersistSession(boolean persistSession) {
this.persistSession = persistSession;
}
public boolean isPersistSession() {
return this.persistSession;
}
@Override
public void setSessionStoreDir(File sessionStoreDir) {
this.sessionStoreDir = sessionStoreDir;
}
public File getSessionStoreDir() {
return this.sessionStoreDir;
}
@Override
public void setInitializers(List<? extends ServletContextInitializer> initializers) {
Assert.notNull(initializers, "Initializers must not be null");
this.initializers = new ArrayList<>(initializers);
}
@Override
public void addInitializers(ServletContextInitializer... initializers) {
Assert.notNull(initializers, "Initializers must not be null");
this.initializers.addAll(Arrays.asList(initializers));
}
@Override
public void setDocumentRoot(File documentRoot) {
this.documentRoot = documentRoot;
}
/**
* Returns the document root which will be used by the web context to serve static
* files.
* @return the document root
*/
public File getDocumentRoot() {
return this.documentRoot;
}
@Override
public void setErrorPages(Set<? extends ErrorPage> errorPages) {
Assert.notNull(errorPages, "ErrorPages must not be null");
this.errorPages = new LinkedHashSet<>(errorPages);
}
@Override
public void addErrorPages(ErrorPage... errorPages) {
Assert.notNull(errorPages, "ErrorPages must not be null");
this.errorPages.addAll(Arrays.asList(errorPages));
}
/**
* Returns a mutable set of {@link ErrorPage ErrorPages} that will be used when
* handling exceptions.
* @return the error pages
*/
public Set<ErrorPage> getErrorPages() {
return this.errorPages;
}
@Override
public void setMimeMappings(MimeMappings mimeMappings) {
this.mimeMappings = new MimeMappings(mimeMappings);
}
/**
* Returns the mime-type mappings.
* @return the mimeMappings the mime-type mappings.
*/
public MimeMappings getMimeMappings() {
return this.mimeMappings;
}
@Override
public void setRegisterDefaultServlet(boolean registerDefaultServlet) {
this.registerDefaultServlet = registerDefaultServlet;
}
/**
* Flag to indicate that the default servlet should be registered.
* @return true if the default servlet is to be registered
*/
public boolean isRegisterDefaultServlet() {
return this.registerDefaultServlet;
}
@Override
public void setSsl(Ssl ssl) {
this.ssl = ssl;
}
public Ssl getSsl() {
return this.ssl;
}
@Override
public void setSslStoreProvider(SslStoreProvider sslStoreProvider) {
this.sslStoreProvider = sslStoreProvider;
}
public SslStoreProvider getSslStoreProvider() {
return this.sslStoreProvider;
}
@Override
public void setJsp(Jsp jsp) {
this.jsp = jsp;
}
public Jsp getJsp() {
return this.jsp;
}
public Compression getCompression() {
return this.compression;
}
@Override
public void setCompression(Compression compression) {
this.compression = compression;
}
public String getServerHeader() {
return this.serverHeader;
}
@Override
public void setServerHeader(String serverHeader) {
this.serverHeader = serverHeader;
}
/**
* Return the Locale to Charset mappings.
* @return the charset mappings
*/
public Map<Locale, Charset> getLocaleCharsetMappings() {
return this.localeCharsetMappings;
}
@Override
public void setLocaleCharsetMappings(Map<Locale, Charset> localeCharsetMappings) {
Assert.notNull(localeCharsetMappings, "localeCharsetMappings must not be null");
this.localeCharsetMappings = localeCharsetMappings;
}
/**
* Utility method that can be used by subclasses wishing to combine the specified
* {@link ServletContextInitializer} parameters with those defined in this instance.
* @param initializers the initializers to merge
* @return a complete set of merged initializers (with the specified parameters
* appearing first)
*/
protected final ServletContextInitializer[] mergeInitializers(
ServletContextInitializer... initializers) {
List<ServletContextInitializer> mergedInitializers = new ArrayList<>();
mergedInitializers.addAll(Arrays.asList(initializers));
mergedInitializers.addAll(this.initializers);
return mergedInitializers
.toArray(new ServletContextInitializer[mergedInitializers.size()]);
}
/**
* Returns whether or not the JSP servlet should be registered with the web server.
* @return {@code true} if the servlet should be registered, otherwise {@code false}
*/
protected boolean shouldRegisterJspServlet() {
return this.jsp != null && this.jsp.getRegistered() && ClassUtils
.isPresent(this.jsp.getClassName(), getClass().getClassLoader());
}
}
...@@ -22,10 +22,15 @@ import java.net.JarURLConnection; ...@@ -22,10 +22,15 @@ import java.net.JarURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.charset.Charset;
import java.security.CodeSource; import java.security.CodeSource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
...@@ -33,34 +38,258 @@ import org.apache.commons.logging.LogFactory; ...@@ -33,34 +38,258 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationHome; import org.springframework.boot.ApplicationHome;
import org.springframework.boot.ApplicationTemp; import org.springframework.boot.ApplicationTemp;
import org.springframework.boot.web.server.WebServerException; import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory;
import org.springframework.boot.web.server.MimeMappings;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* Abstract base class for {@link ServletWebServerFactory} implementations. * Abstract base class for {@link ConfigurableServletWebServerFactory} implementations.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author Ivan Sopov
* @author Eddú Meléndez
* @author Brian Clozel
* @since 2.0.0 * @since 2.0.0
*/ */
public abstract class AbstractServletWebServerFactory extends public abstract class AbstractServletWebServerFactory
AbstractConfigurableServletWebServerFactory implements ServletWebServerFactory { extends AbstractConfigurableWebServerFactory
implements ConfigurableServletWebServerFactory {
protected final Log logger = LogFactory.getLog(getClass()); private static final int DEFAULT_SESSION_TIMEOUT = (int) TimeUnit.MINUTES
.toSeconds(30);
private static final String[] COMMON_DOC_ROOTS = { "src/main/webapp", "public", private static final String[] COMMON_DOC_ROOTS = { "src/main/webapp", "public",
"static" }; "static" };
protected final Log logger = LogFactory.getLog(getClass());
private String contextPath = "";
private String displayName;
private int sessionTimeout = DEFAULT_SESSION_TIMEOUT;
private boolean persistSession;
private File sessionStoreDir;
private boolean registerDefaultServlet = true;
private MimeMappings mimeMappings = new MimeMappings(MimeMappings.DEFAULT);
private File documentRoot;
private List<ServletContextInitializer> initializers = new ArrayList<>();
private Jsp jsp = new Jsp();
private Map<Locale, Charset> localeCharsetMappings = new HashMap<>();
/**
* Create a new {@link AbstractServletWebServerFactory} instance.
*/
public AbstractServletWebServerFactory() { public AbstractServletWebServerFactory() {
super();
} }
/**
* Create a new {@link AbstractServletWebServerFactory} instance with the specified
* port.
* @param port the port number for the web server
*/
public AbstractServletWebServerFactory(int port) { public AbstractServletWebServerFactory(int port) {
super(port); super(port);
} }
/**
* Create a new {@link AbstractServletWebServerFactory} instance with the specified
* context path and port.
* @param contextPath the context path for the web server
* @param port the port number for the web server
*/
public AbstractServletWebServerFactory(String contextPath, int port) { public AbstractServletWebServerFactory(String contextPath, int port) {
super(contextPath, port); super(port);
checkContextPath(contextPath);
this.contextPath = contextPath;
}
/**
* Returns the context path for the web server. The path will start with "/" and not
* end with "/". The root context is represented by an empty string.
* @return the context path
*/
public String getContextPath() {
return this.contextPath;
}
@Override
public void setContextPath(String contextPath) {
checkContextPath(contextPath);
this.contextPath = contextPath;
}
private void checkContextPath(String contextPath) {
Assert.notNull(contextPath, "ContextPath must not be null");
if (contextPath.length() > 0) {
if ("/".equals(contextPath)) {
throw new IllegalArgumentException(
"Root ContextPath must be specified using an empty string");
}
if (!contextPath.startsWith("/") || contextPath.endsWith("/")) {
throw new IllegalArgumentException(
"ContextPath must start with '/' and not end with '/'");
}
}
}
public String getDisplayName() {
return this.displayName;
}
@Override
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
/**
* Return the session timeout in seconds.
* @return the timeout in seconds
*/
public int getSessionTimeout() {
return this.sessionTimeout;
}
@Override
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Override
public void setSessionTimeout(int sessionTimeout, TimeUnit timeUnit) {
Assert.notNull(timeUnit, "TimeUnit must not be null");
this.sessionTimeout = (int) timeUnit.toSeconds(sessionTimeout);
}
public boolean isPersistSession() {
return this.persistSession;
}
@Override
public void setPersistSession(boolean persistSession) {
this.persistSession = persistSession;
}
public File getSessionStoreDir() {
return this.sessionStoreDir;
}
@Override
public void setSessionStoreDir(File sessionStoreDir) {
this.sessionStoreDir = sessionStoreDir;
}
/**
* Flag to indicate that the default servlet should be registered.
* @return true if the default servlet is to be registered
*/
public boolean isRegisterDefaultServlet() {
return this.registerDefaultServlet;
}
@Override
public void setRegisterDefaultServlet(boolean registerDefaultServlet) {
this.registerDefaultServlet = registerDefaultServlet;
}
/**
* Returns the mime-type mappings.
* @return the mimeMappings the mime-type mappings.
*/
public MimeMappings getMimeMappings() {
return this.mimeMappings;
}
@Override
public void setMimeMappings(MimeMappings mimeMappings) {
this.mimeMappings = new MimeMappings(mimeMappings);
}
/**
* Returns the document root which will be used by the web context to serve static
* files.
* @return the document root
*/
public File getDocumentRoot() {
return this.documentRoot;
}
@Override
public void setDocumentRoot(File documentRoot) {
this.documentRoot = documentRoot;
}
@Override
public void setInitializers(List<? extends ServletContextInitializer> initializers) {
Assert.notNull(initializers, "Initializers must not be null");
this.initializers = new ArrayList<>(initializers);
}
@Override
public void addInitializers(ServletContextInitializer... initializers) {
Assert.notNull(initializers, "Initializers must not be null");
this.initializers.addAll(Arrays.asList(initializers));
}
public Jsp getJsp() {
return this.jsp;
}
@Override
public void setJsp(Jsp jsp) {
this.jsp = jsp;
}
/**
* Return the Locale to Charset mappings.
* @return the charset mappings
*/
public Map<Locale, Charset> getLocaleCharsetMappings() {
return this.localeCharsetMappings;
}
@Override
public void setLocaleCharsetMappings(Map<Locale, Charset> localeCharsetMappings) {
Assert.notNull(localeCharsetMappings, "localeCharsetMappings must not be null");
this.localeCharsetMappings = localeCharsetMappings;
}
/**
* Utility method that can be used by subclasses wishing to combine the specified
* {@link ServletContextInitializer} parameters with those defined in this instance.
* @param initializers the initializers to merge
* @return a complete set of merged initializers (with the specified parameters
* appearing first)
*/
protected final ServletContextInitializer[] mergeInitializers(
ServletContextInitializer... initializers) {
List<ServletContextInitializer> mergedInitializers = new ArrayList<>();
mergedInitializers.addAll(Arrays.asList(initializers));
mergedInitializers.addAll(this.initializers);
return mergedInitializers
.toArray(new ServletContextInitializer[mergedInitializers.size()]);
}
/**
* Returns whether or not the JSP servlet should be registered with the web server.
* @return {@code true} if the servlet should be registered, otherwise {@code false}
*/
protected boolean shouldRegisterJspServlet() {
return this.jsp != null && this.jsp.getRegistered() && ClassUtils
.isPresent(this.jsp.getClassName(), getClass().getClassLoader());
} }
/** /**
...@@ -152,7 +381,7 @@ public abstract class AbstractServletWebServerFactory extends ...@@ -152,7 +381,7 @@ public abstract class AbstractServletWebServerFactory extends
} }
} }
File getExplodedWarFileDocumentRoot(File codeSourceFile) { protected final File getExplodedWarFileDocumentRoot(File codeSourceFile) {
if (this.logger.isDebugEnabled()) { if (this.logger.isDebugEnabled()) {
this.logger.debug("Code archive: " + codeSourceFile); this.logger.debug("Code archive: " + codeSourceFile);
} }
...@@ -236,25 +465,4 @@ public abstract class AbstractServletWebServerFactory extends ...@@ -236,25 +465,4 @@ public abstract class AbstractServletWebServerFactory extends
return dir; return dir;
} }
/**
* Returns the absolute temp dir for given server.
* @param prefix server name
* @return The temp dir for given server.
*/
protected File createTempDir(String prefix) {
try {
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
}
catch (IOException ex) {
throw new WebServerException(
"Unable to create tempDir. java.io.tmpdir is set to "
+ System.getProperty("java.io.tmpdir"),
ex);
}
}
} }
...@@ -29,7 +29,7 @@ import org.springframework.boot.web.server.WebServerFactoryCustomizer; ...@@ -29,7 +29,7 @@ import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.boot.web.servlet.ServletContextInitializer;
/** /**
* Simple interface that represents customizations to an {@link ServletWebServerFactory}. * A configurable {@link ServletWebServerFactory}.
* *
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson * @author Andy Wilkinson
...@@ -41,7 +41,7 @@ import org.springframework.boot.web.servlet.ServletContextInitializer; ...@@ -41,7 +41,7 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
* @see WebServerFactoryCustomizer * @see WebServerFactoryCustomizer
*/ */
public interface ConfigurableServletWebServerFactory public interface ConfigurableServletWebServerFactory
extends ConfigurableWebServerFactory { extends ConfigurableWebServerFactory, ServletWebServerFactory {
/** /**
* Sets the context path for the web server. The context should start with a "/" * Sets the context path for the web server. The context should start with a "/"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment