From 6021cb9ca1ccdd0810549f3da5872a75bbc82d7f Mon Sep 17 00:00:00 2001 From: michaeloffner Date: Mon, 19 Aug 2024 20:30:20 +0200 Subject: [PATCH] LDEV-5063 - change visibility to PhysicalClassloader to allow loading Proxy classes from string --- .../commons/lang/PhysicalClassLoader.java | 51 ++++++++++++++++--- .../bytecode/util/JavaProxyFactory.java | 12 +++-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java b/core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java index aef7a0a6d8..a2ef03bd97 100644 --- a/core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java +++ b/core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java @@ -31,6 +31,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader; + import lucee.commons.digest.HashUtil; import lucee.commons.io.CharsetUtil; import lucee.commons.io.IOUtil; @@ -68,7 +70,7 @@ public final class PhysicalClassLoader extends URLClassLoader implements Extenda private Resource directory; private ConfigPro config; - private final ClassLoader parent; + private final ClassLoader addionalClassLoader; private final Collection resources; private Map loadedClasses = new ConcurrentHashMap(); @@ -105,7 +107,7 @@ public static PhysicalClassLoader getPhysicalClassLoader(Config c, Resource dire synchronized (SystemUtil.createToken("PhysicalClassLoader", key)) { rpccl = reload ? null : classLoaders.get(key); if (rpccl == null) { - classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList(), directory, SystemUtil.getCombinedClassLoader(), null, false)); + classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList(), directory, SystemUtil.getCombinedClassLoader(), null, null, false)); } } } @@ -130,19 +132,36 @@ public static PhysicalClassLoader getRPCClassLoader(Config c, JavaSettings js, b } Resource dir = storeResourceMeta(c, key, js, resources); // (Config config, String key, JavaSettings js, Collection _resources) - classLoaders.put(key, rpccl = new PhysicalClassLoader(c, resources, dir, SystemUtil.getCombinedClassLoader(), null, true)); + classLoaders.put(key, rpccl = new PhysicalClassLoader(c, resources, dir, SystemUtil.getCombinedClassLoader(), null, null, true)); + } + } + } + return rpccl; + } + + public static PhysicalClassLoader getRPCClassLoader(Config c, BundleClassLoader bcl, boolean reload) throws IOException { + String key = HashUtil.create64BitHashAsString(bcl + ""); + PhysicalClassLoader rpccl = reload ? null : classLoaders.get(key); + if (rpccl == null) { + synchronized (SystemUtil.createToken("PhysicalClassLoader", key)) { + rpccl = reload ? null : classLoaders.get(key); + if (rpccl == null) { + Resource dir = c.getClassDirectory().getRealResource("RPC/" + key); + if (!dir.exists()) ResourceUtil.createDirectoryEL(dir, true); + // (Config config, String key, JavaSettings js, Collection _resources) + classLoaders.put(key, rpccl = new PhysicalClassLoader(c, new ArrayList(), dir, SystemUtil.getCombinedClassLoader(), bcl, null, true)); } } } return rpccl; } - private PhysicalClassLoader(Config c, List resources, Resource directory, ClassLoader parentClassLoader, PageSourcePool pageSourcePool, boolean rpc) - throws IOException { + private PhysicalClassLoader(Config c, List resources, Resource directory, ClassLoader parentClassLoader, ClassLoader addionalClassLoader, + PageSourcePool pageSourcePool, boolean rpc) throws IOException { super(doURLs(resources), parentClassLoader == null ? (parentClassLoader = SystemUtil.getCombinedClassLoader()) : parentClassLoader); this.resources = resources; config = (ConfigPro) c; - parent = parentClassLoader; + this.addionalClassLoader = addionalClassLoader; this.pageSourcePool = pageSourcePool; // ClassLoader resCL = parent!=null?parent:config.getResourceClassLoader(null); @@ -175,13 +194,20 @@ private Class loadClass(String name, boolean resolve, boolean loadFromFS) thr // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { - // for (ClassLoader p: parents) { try { c = super.loadClass(name, resolve); - // break; } catch (Exception e) { } + + if (addionalClassLoader != null) { + try { + c = addionalClassLoader.loadClass(name); + } + catch (Exception e) { + } + } + // } if (c == null) { if (loadFromFS) c = findClass(name); @@ -201,6 +227,14 @@ protected Class findClass(String name) throws ClassNotFoundException { catch (ClassNotFoundException cnfe) { } + if (addionalClassLoader != null) { + try { + return addionalClassLoader.loadClass(name); + } + catch (ClassNotFoundException e) { + } + } + synchronized (SystemUtil.createToken("pcl", name)) { Resource res = directory.getRealResource(name.replace('.', '/').concat(".class")); @@ -428,4 +462,5 @@ public int compare(Resource l, Resource r) { return l.getAbsolutePath().compareTo(r.getAbsolutePath()); } } + } diff --git a/core/src/main/java/lucee/transformer/bytecode/util/JavaProxyFactory.java b/core/src/main/java/lucee/transformer/bytecode/util/JavaProxyFactory.java index b80ef9b9aa..6d14d54db0 100644 --- a/core/src/main/java/lucee/transformer/bytecode/util/JavaProxyFactory.java +++ b/core/src/main/java/lucee/transformer/bytecode/util/JavaProxyFactory.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Set; +import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; @@ -51,7 +52,6 @@ import lucee.runtime.PageContext; import lucee.runtime.PageContextImpl; import lucee.runtime.config.ConfigWeb; -import lucee.runtime.engine.ThreadLocalPageContext; import lucee.runtime.exp.PageException; import lucee.runtime.op.Caster; import lucee.runtime.op.JavaProxyUtilImpl; @@ -231,6 +231,7 @@ public static Object createProxy(Object defaultValue, PageContext pc, Component public static Object createProxy(PageContext pc, final Component cfc, Class extendz, Class... interfaces) throws PageException, IOException { PageContextImpl pci = (PageContextImpl) pc; PhysicalClassLoader pcl = getRPCClassLoaderFromClasses(pc, extendz, interfaces); + if (pcl == null) pcl = (PhysicalClassLoader) pci.getRPCClassLoader(false); if (extendz == null) extendz = Object.class; @@ -433,7 +434,7 @@ public static Object createProxy(PageContext pc, final Component cfc, Class exte * // adapter.returnValue(); adapter.endMethod(); } */ - private static PhysicalClassLoader getRPCClassLoaderFromClasses(PageContext pc, Class extendz, Class... interfaces) { + private static PhysicalClassLoader getRPCClassLoaderFromClasses(PageContext pc, Class extendz, Class... interfaces) throws IOException { // extends and implement need to come from the same parent classloader PhysicalClassLoader pcl = null; if (extendz != null) { @@ -450,13 +451,16 @@ private static PhysicalClassLoader getRPCClassLoaderFromClasses(PageContext pc, return null; } - public static PhysicalClassLoader getRPCClassLoaderFromClass(PageContext pc, Class clazz) { + public static PhysicalClassLoader getRPCClassLoaderFromClass(PageContext pc, Class clazz) throws IOException { ClassLoader cl = clazz.getClassLoader(); - pc = ThreadLocalPageContext.get(pc); if (cl != null) { if (cl instanceof PhysicalClassLoader) { return ((PhysicalClassLoader) cl); } + else if (cl instanceof BundleClassLoader) { + return PhysicalClassLoader.getRPCClassLoader(pc.getConfig(), (BundleClassLoader) cl, false); + } + } return null; }