From da07cdf41fdfa00c15d7904c73be081728cd1801 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 24 Jul 2013 13:40:27 -0700 Subject: [PATCH] Fix TomcatEmbeddedWebappClassLoader for Tomcat 8 Rework TomcatEmbeddedWebappClassLoader to deal with the fact that the 'system' field is final in Tomcat 8. Issue: #53945989 --- .../TomcatEmbeddedWebappClassLoader.java | 86 +++++++++++++++---- 1 file changed, 71 insertions(+), 15 deletions(-) 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 index 6b81c3fd13b..494c32676f4 100644 --- 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 @@ -1,3 +1,5 @@ +package org.springframework.bootstrap.context.embedded.tomcat; + /* * Copyright 2012-2013 the original author or authors. * @@ -14,11 +16,6 @@ * 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; /** @@ -33,27 +30,86 @@ 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 { + @Override + public synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + + Class resultClass = null; + + // Check local class caches + resultClass = (resultClass == null ? findLoadedClass0(name) : resultClass); + resultClass = (resultClass == null ? findLoadedClass(name) : resultClass); + if (resultClass != null) { + return resolveIfNecessary(resultClass, resolve); + } + + // Check security + checkPackageAccess(name); + + // Perform the actual load + boolean delegateLoad = (this.delegate || filter(name)); + + if (delegateLoad) { + resultClass = (resultClass == null ? loadFromParent(name) : resultClass); + } + resultClass = (resultClass == null ? findClassIgnoringNotFound(name) + : resultClass); + if (!delegateLoad) { + resultClass = (resultClass == null ? loadFromParent(name) : resultClass); + } + + if (resultClass == null) { + throw new ClassNotFoundException(name); + } + + return resolveIfNecessary(resultClass, resolve); + } + + private Class resolveIfNecessary(Class resultClass, boolean resolve) { + if (resolve) { + resolveClass(resultClass); + } + return (resultClass); + } - public EmbeddedSystemClassLoader() { - super(new URL[] {}); + private Class loadFromParent(String name) { + if (this.parent == null) { + return null; } + try { + return Class.forName(name, false, this.parent); + } + catch (ClassNotFoundException e) { + return null; + } + } - @Override - public Class loadClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException( - "System ClassLoader disabled for embedded context, unable to load " - + name); + private Class findClassIgnoringNotFound(String name) { + try { + return findClass(name); } + catch (ClassNotFoundException e) { + return null; + } + } + private void checkPackageAccess(String name) throws ClassNotFoundException { + if (this.securityManager != null && name.lastIndexOf('.') >= 0) { + try { + this.securityManager.checkPackageAccess(name.substring(0, + name.lastIndexOf('.'))); + } + catch (SecurityException se) { + throw new ClassNotFoundException("Security Violation, attempt to use " + + "Restricted Class: " + name, se); + } + } } }