|
20 | 20 | import java.io.IOException;
|
21 | 21 | import java.io.InputStream;
|
22 | 22 | import java.lang.reflect.Method;
|
| 23 | +import java.net.MalformedURLException; |
| 24 | +import java.net.URL; |
| 25 | +import java.net.URLClassLoader; |
23 | 26 | import java.nio.charset.Charset;
|
24 | 27 | import java.util.ArrayList;
|
25 | 28 | import java.util.Arrays;
|
|
37 | 40 | import org.apache.catalina.Valve;
|
38 | 41 | import org.apache.catalina.Wrapper;
|
39 | 42 | import org.apache.catalina.connector.Connector;
|
| 43 | +import org.apache.catalina.core.StandardContext; |
40 | 44 | import org.apache.catalina.loader.WebappLoader;
|
41 | 45 | import org.apache.catalina.startup.Tomcat;
|
42 | 46 | import org.apache.catalina.startup.Tomcat.FixContextListener;
|
43 | 47 | import org.apache.coyote.AbstractProtocol;
|
| 48 | +import org.apache.naming.resources.FileDirContext; |
44 | 49 | import org.springframework.beans.BeanUtils;
|
45 | 50 | import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
46 | 51 | import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
@@ -584,6 +589,95 @@ private void onStart(Context context) {
|
584 | 589 | if (servletContext.getAttribute(this.MERGED_WEB_XML) == null) {
|
585 | 590 | servletContext.setAttribute(this.MERGED_WEB_XML, getEmptyWebXml());
|
586 | 591 | }
|
| 592 | + addClasspathResources(context); |
| 593 | + } |
| 594 | + |
| 595 | + private void addClasspathResources(Context context) { |
| 596 | + ClassLoader loader = getClass().getClassLoader(); |
| 597 | + if (loader instanceof URLClassLoader) { |
| 598 | + for (URL url : ((URLClassLoader) loader).getURLs()) { |
| 599 | + String file = url.getFile(); |
| 600 | + if (file.endsWith(".jar") || file.endsWith(".jar!/")) { |
| 601 | + addJarContext(context, url); |
| 602 | + } |
| 603 | + else if (url.toString().startsWith("file:")) { |
| 604 | + addDirContext(context, url); |
| 605 | + } |
| 606 | + } |
| 607 | + } |
| 608 | + } |
| 609 | + |
| 610 | + private void addJarContext(Context context, URL url) { |
| 611 | + String jar = url.toString(); |
| 612 | + if (!jar.startsWith("jar:")) { |
| 613 | + // A jar file in the file system. Convert to Jar URL. |
| 614 | + jar = "jar:" + jar + "!/"; |
| 615 | + } |
| 616 | + if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) { |
| 617 | + // Tomcat 7 |
| 618 | + try { |
| 619 | + context.addResourceJarUrl(new URL(jar)); |
| 620 | + } |
| 621 | + catch (MalformedURLException e) { |
| 622 | + // Ignore? |
| 623 | + } |
| 624 | + } |
| 625 | + else { |
| 626 | + // Tomcat 8 |
| 627 | + addResourceSet(context, "RESOURCE_JAR", jar); |
| 628 | + } |
| 629 | + } |
| 630 | + |
| 631 | + private void addDirContext(Context context, URL url) { |
| 632 | + String dir = url.toString().substring("file:".length()); |
| 633 | + if (new File(dir).isDirectory()) { |
| 634 | + if (ClassUtils.isPresent("org.apache.catalina.deploy.ErrorPage", null)) { |
| 635 | + // Tomcat 7 |
| 636 | + if (context instanceof StandardContext) { |
| 637 | + FileDirContext files = new FileDirContext(); |
| 638 | + files.setDocBase(dir); |
| 639 | + ((StandardContext) context).addResourcesDirContext(files); |
| 640 | + } |
| 641 | + } |
| 642 | + else { |
| 643 | + // Tomcat 8 |
| 644 | + addResourceSet(context, "RESOURCE_JAR", url.toString()); |
| 645 | + } |
| 646 | + } |
| 647 | + } |
| 648 | + |
| 649 | + @SuppressWarnings({ "rawtypes", "unchecked" }) |
| 650 | + private void addResourceSet(Context context, String name, String dir) { |
| 651 | + Object resources; |
| 652 | + Method create; |
| 653 | + Class type; |
| 654 | + try { |
| 655 | + Method getResources = ReflectionUtils.findMethod(context.getClass(), |
| 656 | + "getResources"); |
| 657 | + resources = getResources.invoke(context); |
| 658 | + type = ClassUtils.resolveClassName( |
| 659 | + "org.apache.catalina.WebResourceRoot.ResourceSetType", null); |
| 660 | + create = ReflectionUtils.findMethod(resources.getClass(), |
| 661 | + "createWebResourceSet", type, String.class, URL.class, |
| 662 | + String.class); |
| 663 | + } |
| 664 | + catch (Exception e) { |
| 665 | + throw new IllegalStateException("Tomcat 8 reflection failed", e); |
| 666 | + } |
| 667 | + try { |
| 668 | + if (dir.indexOf("!/") < dir.lastIndexOf("!/")) { |
| 669 | + // It's a nested jar but we now don't want the suffix because Tomcat |
| 670 | + // is going to try and locate it as a root URL (not the resource |
| 671 | + // inside it) |
| 672 | + dir = dir.substring(0, dir.length() - 2); |
| 673 | + } |
| 674 | + URL url = new URL(dir); |
| 675 | + String path = "/META-INF/resources"; |
| 676 | + create.invoke(resources, Enum.valueOf(type, name), "/", url, path); |
| 677 | + } |
| 678 | + catch (Exception e) { |
| 679 | + // Ignore (probably not a directory) |
| 680 | + } |
587 | 681 | }
|
588 | 682 |
|
589 | 683 | private String getEmptyWebXml() {
|
|
0 commit comments