|
|
|
@ -18,6 +18,8 @@ package org.springframework.boot.web.embedded.tomcat;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.nio.charset.Charset;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
@ -39,16 +41,23 @@ import org.apache.catalina.Engine;
|
|
|
|
|
import org.apache.catalina.Host;
|
|
|
|
|
import org.apache.catalina.Lifecycle;
|
|
|
|
|
import org.apache.catalina.LifecycleEvent;
|
|
|
|
|
import org.apache.catalina.LifecycleException;
|
|
|
|
|
import org.apache.catalina.LifecycleListener;
|
|
|
|
|
import org.apache.catalina.Manager;
|
|
|
|
|
import org.apache.catalina.Valve;
|
|
|
|
|
import org.apache.catalina.WebResource;
|
|
|
|
|
import org.apache.catalina.WebResourceRoot.ResourceSetType;
|
|
|
|
|
import org.apache.catalina.WebResourceSet;
|
|
|
|
|
import org.apache.catalina.Wrapper;
|
|
|
|
|
import org.apache.catalina.connector.Connector;
|
|
|
|
|
import org.apache.catalina.loader.WebappLoader;
|
|
|
|
|
import org.apache.catalina.session.StandardManager;
|
|
|
|
|
import org.apache.catalina.startup.Tomcat;
|
|
|
|
|
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
|
|
|
|
import org.apache.catalina.util.LifecycleBase;
|
|
|
|
|
import org.apache.catalina.webresources.AbstractResourceSet;
|
|
|
|
|
import org.apache.catalina.webresources.EmptyResource;
|
|
|
|
|
import org.apache.catalina.webresources.StandardRoot;
|
|
|
|
|
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
|
|
|
|
|
import org.apache.coyote.AbstractProtocol;
|
|
|
|
|
import org.apache.coyote.ProtocolHandler;
|
|
|
|
@ -71,6 +80,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;
|
|
|
|
|
import org.springframework.util.ResourceUtils;
|
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
@ -183,12 +193,16 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
|
|
|
|
|
File docBase = getValidDocumentRoot();
|
|
|
|
|
docBase = (docBase != null ? docBase : createTempDir("tomcat-docbase"));
|
|
|
|
|
File documentRoot = getValidDocumentRoot();
|
|
|
|
|
final TomcatEmbeddedContext context = new TomcatEmbeddedContext();
|
|
|
|
|
if (documentRoot != null) {
|
|
|
|
|
context.setResources(new LoaderHidingResourceRoot(context));
|
|
|
|
|
}
|
|
|
|
|
context.setName(getContextPath());
|
|
|
|
|
context.setDisplayName(getDisplayName());
|
|
|
|
|
context.setPath(getContextPath());
|
|
|
|
|
File docBase = (documentRoot != null ? documentRoot
|
|
|
|
|
: createTempDir("tomcat-docbase"));
|
|
|
|
|
context.setDocBase(docBase.getAbsolutePath());
|
|
|
|
|
context.addLifecycleListener(new FixContextListener());
|
|
|
|
|
context.setParentClassLoader(
|
|
|
|
@ -839,4 +853,96 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class LoaderHidingResourceRoot extends StandardRoot {
|
|
|
|
|
|
|
|
|
|
private LoaderHidingResourceRoot(TomcatEmbeddedContext context) {
|
|
|
|
|
super(context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected WebResourceSet createMainResourceSet() {
|
|
|
|
|
return new LoaderHidingWebResourceSet(super.createMainResourceSet());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class LoaderHidingWebResourceSet extends AbstractResourceSet {
|
|
|
|
|
|
|
|
|
|
private final WebResourceSet delegate;
|
|
|
|
|
|
|
|
|
|
private final Method initInternal;
|
|
|
|
|
|
|
|
|
|
private LoaderHidingWebResourceSet(WebResourceSet delegate) {
|
|
|
|
|
this.delegate = delegate;
|
|
|
|
|
try {
|
|
|
|
|
this.initInternal = LifecycleBase.class.getDeclaredMethod("initInternal");
|
|
|
|
|
this.initInternal.setAccessible(true);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex) {
|
|
|
|
|
throw new IllegalStateException(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public WebResource getResource(String path) {
|
|
|
|
|
if (path.startsWith("/org/springframework/boot")) {
|
|
|
|
|
return new EmptyResource(getRoot(), path);
|
|
|
|
|
}
|
|
|
|
|
return this.delegate.getResource(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String[] list(String path) {
|
|
|
|
|
return this.delegate.list(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Set<String> listWebAppPaths(String path) {
|
|
|
|
|
return this.delegate.listWebAppPaths(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean mkdir(String path) {
|
|
|
|
|
return this.delegate.mkdir(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean write(String path, InputStream is, boolean overwrite) {
|
|
|
|
|
return this.delegate.write(path, is, overwrite);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public URL getBaseUrl() {
|
|
|
|
|
return this.delegate.getBaseUrl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setReadOnly(boolean readOnly) {
|
|
|
|
|
this.delegate.setReadOnly(readOnly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean isReadOnly() {
|
|
|
|
|
return this.delegate.isReadOnly();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void gc() {
|
|
|
|
|
this.delegate.gc();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void initInternal() throws LifecycleException {
|
|
|
|
|
if (this.delegate instanceof LifecycleBase) {
|
|
|
|
|
try {
|
|
|
|
|
ReflectionUtils.invokeMethod(this.initInternal, this.delegate);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex) {
|
|
|
|
|
throw new LifecycleException(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|