From 510e16a809ec7125ef68a2e94e2dd29d58352fc7 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 4 Jul 2013 22:35:52 -0700 Subject: [PATCH] Don't consider system ClassLoader in Tomcat Modify TomcatEmbeddedServletContainerFactory to ensure that the system ClassLoader is not considered when loading classes. This is required to fix issues when working with executable JARs created with the maven plugin. --- ...TomcatEmbeddedServletContainerFactory.java | 10 +++- .../TomcatEmbeddedWebappClassLoader.java | 59 +++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index b4c32f7a31..42bd98c1f9 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -34,6 +34,7 @@ import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardEngine; import org.apache.catalina.core.StandardHost; import org.apache.catalina.core.StandardService; +import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat.FixContextListener; import org.apache.coyote.AbstractProtocol; @@ -139,9 +140,12 @@ public class TomcatEmbeddedServletContainerFactory extends context.setPath(getContextPath()); context.setDocBase(docBase.getAbsolutePath()); context.addLifecycleListener(new FixContextListener()); - if (this.resourceLoader != null) { - context.setParentClassLoader(this.resourceLoader.getClassLoader()); - } + context.setParentClassLoader(this.resourceLoader != null ? this.resourceLoader + .getClassLoader() : ClassUtils.getDefaultClassLoader()); + WebappLoader loader = new WebappLoader(context.getParentClassLoader()); + loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName()); + context.setLoader(loader); + if (isRegisterDefaultServlet()) { addDefaultServlet(context); } diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java new file mode 100644 index 0000000000..6b81c3fd13 --- /dev/null +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012-2013 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.bootstrap.context.embedded.tomcat; + +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.catalina.loader.WebappClassLoader; + +/** + * Extension of Tomcat's {@link WebappClassLoader} that does not consider the + * {@link ClassLoader#getSystemClassLoader() system classloader}. This is required to to + * ensure that any custom context classloader is always used (as is the case with some + * executable archives). + * + * @author Phillip Webb + */ +public class TomcatEmbeddedWebappClassLoader extends WebappClassLoader { + + public TomcatEmbeddedWebappClassLoader() { + super(); + this.system = new EmbeddedSystemClassLoader(); + } + + public TomcatEmbeddedWebappClassLoader(ClassLoader parent) { + super(parent); + this.system = new EmbeddedSystemClassLoader(); + } + + private static class EmbeddedSystemClassLoader extends URLClassLoader { + + public EmbeddedSystemClassLoader() { + super(new URL[] {}); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException( + "System ClassLoader disabled for embedded context, unable to load " + + name); + } + + } + +}