Hack around with Tomcat resource paths
Tomcat 8 has different APIs again so it was quite difficult to get it working and test it. The test is manual anyway (multi-module project with JSPs in /META-INF/resources, not part of the samples), and requires you to build a war and execute it (since the resource paths are different when it's an archive). Fixes gh-1131
This commit is contained in:
parent
51496b4e4f
commit
1bcc136374
|
|
@ -20,6 +20,9 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -37,10 +40,12 @@ import org.apache.catalina.LifecycleListener;
|
||||||
import org.apache.catalina.Valve;
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.Wrapper;
|
import org.apache.catalina.Wrapper;
|
||||||
import org.apache.catalina.connector.Connector;
|
import org.apache.catalina.connector.Connector;
|
||||||
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.loader.WebappLoader;
|
import org.apache.catalina.loader.WebappLoader;
|
||||||
import org.apache.catalina.startup.Tomcat;
|
import org.apache.catalina.startup.Tomcat;
|
||||||
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
||||||
import org.apache.coyote.AbstractProtocol;
|
import org.apache.coyote.AbstractProtocol;
|
||||||
|
import org.apache.naming.resources.FileDirContext;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||||
|
|
@ -584,6 +589,95 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||||
if (servletContext.getAttribute(this.MERGED_WEB_XML) == null) {
|
if (servletContext.getAttribute(this.MERGED_WEB_XML) == null) {
|
||||||
servletContext.setAttribute(this.MERGED_WEB_XML, getEmptyWebXml());
|
servletContext.setAttribute(this.MERGED_WEB_XML, getEmptyWebXml());
|
||||||
}
|
}
|
||||||
|
addClasspathResources(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addClasspathResources(Context context) {
|
||||||
|
ClassLoader loader = getClass().getClassLoader();
|
||||||
|
if (loader instanceof URLClassLoader) {
|
||||||
|
for (URL url : ((URLClassLoader) loader).getURLs()) {
|
||||||
|
String file = url.getFile();
|
||||||
|
if (file.endsWith(".jar") || file.endsWith(".jar!/")) {
|
||||||
|
addJarContext(context, url);
|
||||||
|
}
|
||||||
|
else if (url.toString().startsWith("file:")) {
|
||||||
|
addDirContext(context, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJarContext(Context context, URL url) {
|
||||||
|
String jar = url.toString();
|
||||||
|
if (!jar.startsWith("jar:")) {
|
||||||
|
// A jar file in the file system. Convert to Jar URL.
|
||||||
|
jar = "jar:" + jar + "!/";
|
||||||
|
}
|
||||||
|
if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) {
|
||||||
|
// Tomcat 7
|
||||||
|
try {
|
||||||
|
context.addResourceJarUrl(new URL(jar));
|
||||||
|
}
|
||||||
|
catch (MalformedURLException e) {
|
||||||
|
// Ignore?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Tomcat 8
|
||||||
|
addResourceSet(context, "RESOURCE_JAR", jar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDirContext(Context context, URL url) {
|
||||||
|
String dir = url.toString().substring("file:".length());
|
||||||
|
if (new File(dir).isDirectory()) {
|
||||||
|
if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) {
|
||||||
|
// Tomcat 7
|
||||||
|
if (context instanceof StandardContext) {
|
||||||
|
FileDirContext files = new FileDirContext();
|
||||||
|
files.setDocBase(dir);
|
||||||
|
((StandardContext) context).addResourcesDirContext(files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Tomcat 8
|
||||||
|
addResourceSet(context, "RESOURCE_JAR", url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
private void addResourceSet(Context context, String name, String dir) {
|
||||||
|
Object resources;
|
||||||
|
Method create;
|
||||||
|
Class type;
|
||||||
|
try {
|
||||||
|
Method getResources = ReflectionUtils.findMethod(context.getClass(),
|
||||||
|
"getResources");
|
||||||
|
resources = getResources.invoke(context);
|
||||||
|
type = ClassUtils.resolveClassName(
|
||||||
|
"org.apache.catalina.WebResourceRoot.ResourceSetType", null);
|
||||||
|
create = ReflectionUtils.findMethod(resources.getClass(),
|
||||||
|
"createWebResourceSet", type, String.class, URL.class,
|
||||||
|
String.class);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new IllegalStateException("Tomcat 8 reflection failed", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (dir.indexOf("!/") < dir.lastIndexOf("!/")) {
|
||||||
|
// It's a nested jar but we now don't want the suffix because Tomcat
|
||||||
|
// is going to try and locate it as a root URL (not the resource
|
||||||
|
// inside it)
|
||||||
|
dir = dir.substring(0, dir.length() - 2);
|
||||||
|
}
|
||||||
|
URL url = new URL(dir);
|
||||||
|
String path = "/META-INF/resources";
|
||||||
|
create.invoke(resources, Enum.valueOf(type, name), "/", url, path);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// Ignore (probably not a directory)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEmptyWebXml() {
|
private String getEmptyWebXml() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue