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
pull/1132/head
Dave Syer 11 years ago
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…
Cancel
Save