diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java index 34e9e58f9e..4a2e92dee1 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java @@ -16,7 +16,10 @@ package org.springframework.boot.web.embedded.tomcat; +import java.io.IOException; import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; import org.apache.catalina.loader.WebappClassLoader; import org.apache.commons.logging.Log; @@ -44,6 +47,16 @@ public class TomcatEmbeddedWebappClassLoader extends WebappClassLoader { super(parent); } + @Override + public URL findResource(String name) { + return null; + } + + @Override + public Enumeration findResources(String name) throws IOException { + return Collections.emptyEnumeration(); + } + @Override public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { diff --git a/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java b/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java new file mode 100644 index 0000000000..d73840b91d --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatEmbeddedWebappClassLoaderTests.java @@ -0,0 +1,119 @@ +/* + * Copyright 2012-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.embedded.tomcat; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; + +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.loader.WebappClassLoader; +import org.apache.catalina.webresources.StandardRoot; +import org.apache.catalina.webresources.WarResourceSet; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import org.springframework.util.CollectionUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link TomcatEmbeddedWebappClassLoader}. + * + * @author Andy Wilkinson + */ +public class TomcatEmbeddedWebappClassLoaderTests { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void getResourceFindsResourceFromParentClassLoader() throws Exception { + File war = createWar(); + withWebappClassLoader(war, (classLoader) -> { + assertThat(classLoader.getResource("test.txt")) + .isEqualTo(new URL(webInfClassesUrlString(war) + "test.txt")); + }); + } + + @Test + public void getResourcesOnlyFindsResourcesFromParentClassLoader() throws Exception { + File warFile = createWar(); + withWebappClassLoader(warFile, (classLoader) -> { + List urls = new ArrayList<>(); + CollectionUtils.toIterator(classLoader.getResources("test.txt")) + .forEachRemaining(urls::add); + assertThat(urls).containsExactly( + new URL(webInfClassesUrlString(warFile) + "test.txt")); + }); + } + + private void withWebappClassLoader(File war, ClassLoaderConsumer consumer) + throws Exception { + URLClassLoader parent = new URLClassLoader( + new URL[] { new URL(webInfClassesUrlString(war)) }, null); + try (WebappClassLoader classLoader = new TomcatEmbeddedWebappClassLoader( + parent)) { + StandardContext context = new StandardContext(); + context.setName("test"); + StandardRoot resources = new StandardRoot(); + resources.setContext(context); + resources.addJarResources( + new WarResourceSet(resources, "/", war.getAbsolutePath())); + resources.start(); + classLoader.setResources(resources); + classLoader.start(); + consumer.accept(classLoader); + } + } + + private String webInfClassesUrlString(File war) { + return "jar:file:" + war.getAbsolutePath() + "!/WEB-INF/classes/"; + } + + private File createWar() throws IOException, FileNotFoundException { + File warFile = this.temp.newFile("test.war"); + try (JarOutputStream warOut = new JarOutputStream( + new FileOutputStream(warFile))) { + createEntries(warOut, "WEB-INF/", "WEB-INF/classes/", + "WEB-INF/classes/test.txt"); + } + return warFile; + } + + private void createEntries(JarOutputStream out, String... names) throws IOException { + for (String name : names) { + out.putNextEntry(new ZipEntry(name)); + out.closeEntry(); + } + } + + private interface ClassLoaderConsumer { + + void accept(ClassLoader classLoader) throws Exception; + + } + +}