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.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -37,10 +40,12 @@ 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.apache.naming.resources.FileDirContext;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
|
|
@ -584,6 +589,95 @@ public class TomcatEmbeddedServletContainerFactory extends
|
|||
if (servletContext.getAttribute(this.MERGED_WEB_XML) == null) {
|
||||
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() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue