From 454a9fd17653ce3bceba58a9ba989e344ee2c7c7 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 26 Mar 2024 21:40:09 +0100 Subject: [PATCH] Allow classes to be loaded via plugin loader When a plugin is used, additional RMI classes may be added to the codebase. These need to be taken into account when loading remote objects from the RMI registry. --- .../rmg/internal/CodebaseCollector.java | 84 ++++++++++++++++--- .../rmg/networking/RMIRegistryEndpoint.java | 2 +- src/eu/tneitzel/rmg/plugin/PluginSystem.java | 5 +- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/src/eu/tneitzel/rmg/internal/CodebaseCollector.java b/src/eu/tneitzel/rmg/internal/CodebaseCollector.java index 6977e2a..c02272d 100644 --- a/src/eu/tneitzel/rmg/internal/CodebaseCollector.java +++ b/src/eu/tneitzel/rmg/internal/CodebaseCollector.java @@ -7,6 +7,7 @@ import java.util.HashSet; import java.util.Set; +import eu.tneitzel.rmg.plugin.PluginSystem; import eu.tneitzel.rmg.utils.RMGUtils; import javassist.CannotCompileException; import javassist.NotFoundException; @@ -87,18 +88,42 @@ public class CodebaseCollector extends RMIClassLoaderSpi */ public Class loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { - Class resolvedClass = null; - long serialVersionUID = RMGOption.SERIAL_VERSION_UID.getValue(); - addCodebase(codebase, name); codebase = null; + long serialVersionUID = RMGOption.SERIAL_VERSION_UID.getValue(); + if (serialVersionUIDMap.containsKey(name)) { serialVersionUID = serialVersionUIDMap.get(name); name = "_" + name; } + else + { + try + { + // attempt to load the class directly + return originalLoader.loadClass(codebase, name, defaultLoader); + } + + catch (ClassNotFoundException e) {} + + if (PluginSystem.pluginLoader != null) + { + try + { + // if a plugin is used attempt to load the class via the plugin loader + return originalLoader.loadClass(codebase, name, PluginSystem.pluginLoader); + } + + catch (ClassNotFoundException e) {} + } + } + + // class could neither be loaded directly nor via plugin. Dynamic creation is required. + Class resolvedClass = null; + try { if (name.endsWith("_Stub")) @@ -147,19 +172,47 @@ else if (name.contains("SocketFactory") || name.endsWith("Factory") || name.ends */ public Class loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { + for (String intf : interfaces) + { + addCodebase(codebase, intf); + } + + codebase = null; Class resolvedClass = null; - try { + try + { + // attempt to load the class directly without dynamic class creation + return originalLoader.loadProxyClass(codebase, interfaces, defaultLoader); + } + + catch (ClassNotFoundException e) {} + + if (PluginSystem.pluginLoader != null) + { + try + { + // if a plugin is used, attempt to load the class from the plugin loader + return originalLoader.loadProxyClass(codebase, interfaces, PluginSystem.pluginLoader); + } + + catch (ClassNotFoundException e) {} + } - for(String intf : interfaces) { + try + { + // the class could neither be loaded directly nor via plugin. Dynamic creation is required + for (String intf : interfaces) + { RMGUtils.makeInterface(intf); - addCodebase(codebase, intf); } - codebase = null; resolvedClass = originalLoader.loadProxyClass(codebase, interfaces, defaultLoader); - } catch (CannotCompileException e) { + } + + catch (CannotCompileException e) + { ExceptionHandler.internalError("loadProxyClass", "Unable to compile unknown interface class."); } @@ -235,17 +288,24 @@ public static void addSerialVersionUID(String className, long serialVersionUID) */ private void addCodebase(String codebase, String className) { - if( codebase == null ) + if (codebase == null) + { return; + } - if( className.startsWith("java.") || className.startsWith("[Ljava") || className.startsWith("javax.") ) + if (className.startsWith("java.") || className.startsWith("[Ljava") || className.startsWith("javax.")) + { codebases.putIfAbsent(codebase, new HashSet()); + } - else if( codebases.containsKey(codebase) ) { + else if (codebases.containsKey(codebase)) + { Set classNames = codebases.get(codebase); classNames.add(className); + } - } else { + else + { Set classNames = new HashSet(); classNames.add(className); codebases.put(codebase, classNames); diff --git a/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java b/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java index aec3e4d..e3290ad 100644 --- a/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java +++ b/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java @@ -219,7 +219,7 @@ public Remote lookup(String boundName) throws UnmarshalException ExceptionHandler.notBoundException(e, boundName); } - catch( Exception e ) + catch (Exception e) { Throwable cause = ExceptionHandler.getCause(e); diff --git a/src/eu/tneitzel/rmg/plugin/PluginSystem.java b/src/eu/tneitzel/rmg/plugin/PluginSystem.java index f394735..34fd163 100644 --- a/src/eu/tneitzel/rmg/plugin/PluginSystem.java +++ b/src/eu/tneitzel/rmg/plugin/PluginSystem.java @@ -34,6 +34,7 @@ public class PluginSystem { private static String manifestAttribute = "RmgPluginClass"; + public static URLClassLoader pluginLoader = null; private static IActionProvider actionProvider = null; private static IPayloadProvider payloadProvider = null; @@ -115,8 +116,8 @@ private static void loadPlugin(String pluginPath) try { - URLClassLoader ucl = new URLClassLoader(new URL[] {pluginFile.toURI().toURL()}); - Class pluginClass = Class.forName(pluginClassName, true, ucl); + pluginLoader = new URLClassLoader(new URL[] {pluginFile.toURI().toURL()}); + Class pluginClass = Class.forName(pluginClassName, true, pluginLoader); pluginInstance = pluginClass.newInstance(); }