diff options
Diffstat (limited to 'java/src')
-rw-r--r-- | java/src/Ice/PluginManagerI.java | 248 | ||||
-rw-r--r-- | java/src/IceBox/ServiceManagerI.java | 166 | ||||
-rw-r--r-- | java/src/IceInternal/Instance.java | 2 | ||||
-rw-r--r-- | java/src/IceInternal/Util.java | 1 |
4 files changed, 351 insertions, 66 deletions
diff --git a/java/src/Ice/PluginManagerI.java b/java/src/Ice/PluginManagerI.java index e3c569f5f75..8445fb8e55f 100644 --- a/java/src/Ice/PluginManagerI.java +++ b/java/src/Ice/PluginManagerI.java @@ -29,10 +29,10 @@ public final class PluginManagerI implements PluginManager java.util.List<Plugin> initializedPlugins = new java.util.ArrayList<Plugin>(); try { - for(Plugin p : _initOrder) + for(PluginInfo p : _plugins) { - p.initialize(); - initializedPlugins.add(p); + p.plugin.initialize(); + initializedPlugins.add(p.plugin); } } catch(RuntimeException ex) @@ -64,9 +64,9 @@ public final class PluginManagerI implements PluginManager getPlugins() { java.util.ArrayList<String> names = new java.util.ArrayList<String>(); - for(java.util.Map.Entry<String, Plugin> p : _plugins.entrySet()) + for(PluginInfo p : _plugins) { - names.add(p.getKey()); + names.add(p.name); } return names.toArray(new String[0]); } @@ -79,11 +79,12 @@ public final class PluginManagerI implements PluginManager throw new CommunicatorDestroyedException(); } - Plugin p = _plugins.get(name); + Plugin p = findPlugin(name); if(p != null) { return p; } + NotRegisteredException ex = new NotRegisteredException(); ex.id = name; ex.kindOfObject = _kindOfObject; @@ -98,14 +99,18 @@ public final class PluginManagerI implements PluginManager throw new CommunicatorDestroyedException(); } - if(_plugins.containsKey(name)) + if(findPlugin(name) != null) { AlreadyRegisteredException ex = new AlreadyRegisteredException(); ex.id = name; ex.kindOfObject = _kindOfObject; throw ex; } - _plugins.put(name, plugin); + + PluginInfo info = new PluginInfo(); + info.name = name; + info.plugin = plugin; + _plugins.add(info); } public synchronized void @@ -115,28 +120,38 @@ public final class PluginManagerI implements PluginManager { if(_initialized) { - for(java.util.Map.Entry<String, Plugin> p : _plugins.entrySet()) + java.util.ListIterator<PluginInfo> i = _plugins.listIterator(_plugins.size()); + while(i.hasPrevious()) { + PluginInfo p = i.previous(); try { - p.getValue().destroy(); + p.plugin.destroy(); } catch(RuntimeException ex) { - Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" + p.getKey() + - "' destruction:\n" + ex.toString()); + Ice.Util.getProcessLogger().warning("unexpected exception raised by plug-in `" + + p.name + "' destruction:\n" + ex.toString()); } } } _communicator = null; } + + _plugins.clear(); + + if(_classLoaders != null) + { + _classLoaders.clear(); + } } public - PluginManagerI(Communicator communicator) + PluginManagerI(Communicator communicator, IceInternal.Instance instance) { _communicator = communicator; + _instance = instance; _initialized = false; } @@ -163,7 +178,7 @@ public final class PluginManagerI implements PluginManager final String[] loadOrder = properties.getPropertyAsList("Ice.PluginLoadOrder"); for(String name : loadOrder) { - if(_plugins.containsKey(name)) + if(findPlugin(name) != null) { PluginInitializationException ex = new PluginInitializationException(); ex.reason = "plug-in `" + name + "' already loaded"; @@ -181,7 +196,7 @@ public final class PluginManagerI implements PluginManager key = "Ice.Plugin." + name; hasKey = plugins.containsKey(key); } - + if(hasKey) { final String value = plugins.get(key); @@ -222,10 +237,10 @@ public final class PluginManagerI implements PluginManager name = name.substring(0, dotPos); loadPlugin(name, entry.getValue(), cmdArgs); p.remove(); - + // // Don't want to load this one if it's there! - // + // plugins.remove("Ice.Plugin." + name); } else @@ -236,7 +251,7 @@ public final class PluginManagerI implements PluginManager dotPos = -1; } } - + if(dotPos == -1) { // @@ -250,7 +265,7 @@ public final class PluginManagerI implements PluginManager { value = javaValue; } - + loadPlugin(name, value, cmdArgs); } } @@ -262,31 +277,88 @@ public final class PluginManagerI implements PluginManager assert(_communicator != null); // - // Separate the entry point from the arguments. + // We support the following formats: // - String className; + // <class-name> [args] + // <jar-file>:<class-name> [args] + // <class-dir>:<class-name> [args] + // "<path with spaces>":<class-name> [args] + // "<path with spaces>:<class-name>" [args] + // + String[] args; - int pos = pluginSpec.indexOf(' '); - if(pos == -1) + try { - pos = pluginSpec.indexOf('\t'); + args = IceUtilInternal.Options.split(pluginSpec); } - if(pos == -1) + catch(IceUtilInternal.Options.BadQuote ex) + { + throw new PluginInitializationException("invalid arguments for plug-in `" + name + "':\n" + + ex.getMessage()); + } + + assert(args.length > 0); + + final String entryPoint = args[0]; + + final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + boolean absolutePath = false; + + // + // Find first ':' that isn't part of the file path. + // + int pos = entryPoint.indexOf(':'); + if(isWindows) + { + final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 && + (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/')) + { + absolutePath = true; + pos = entryPoint.indexOf(':', pos + 1); + } + if(!absolutePath) + { + absolutePath = entryPoint.startsWith("\\\\"); + } + } + else + { + absolutePath = entryPoint.startsWith("/"); + } + + if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1)) { - pos = pluginSpec.indexOf('\n'); + // + // Class name is missing. + // + throw new PluginInitializationException("invalid entry point for plug-in `" + name + "':\n" + entryPoint); } + + // + // Extract the JAR file or subdirectory, if any. + // + String classDir = null; // Path name of JAR file or subdirectory. + String className; + if(pos == -1) { - className = pluginSpec; - args = new String[0]; + className = entryPoint; } else { - className = pluginSpec.substring(0, pos); - args = pluginSpec.substring(pos).trim().split("[ \t\n]+", pos); + classDir = entryPoint.substring(0, pos).trim(); + className = entryPoint.substring(pos + 1).trim(); } // + // Shift the arguments. + // + String[] tmp = new String[args.length - 1]; + System.arraycopy(args, 1, tmp, 0, args.length - 1); + args = tmp; + + // // Convert command-line options into properties. First we // convert the options from the plug-in configuration, then // we convert the options from the application command-line. @@ -301,13 +373,85 @@ public final class PluginManagerI implements PluginManager PluginFactory pluginFactory = null; try { - Class<?> c = IceInternal.Util.getInstance(_communicator).findClass(className); + Class<?> c = null; + + // + // Use a class loader if the user specified a JAR file or class directory. + // + if(classDir != null) + { + try + { + if(!absolutePath) + { + classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator + + classDir).getCanonicalPath(); + } + + if(!classDir.endsWith(java.io.File.separator) && !classDir.toLowerCase().endsWith(".jar")) + { + classDir += java.io.File.separator; + } + + // + // Reuse an existing class loader if we have already loaded a plug-in with + // the same value for classDir, otherwise create a new one. + // + ClassLoader cl = null; + + if(_classLoaders == null) + { + _classLoaders = new java.util.HashMap<String, ClassLoader>(); + } + else + { + cl = _classLoaders.get(classDir); + } + + if(cl == null) + { + final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file:///" + classDir) }; + + // + // Use the custom class loader (if any) as the parent. + // + if(_instance.initializationData().classLoader != null) + { + cl = new java.net.URLClassLoader(url, _instance.initializationData().classLoader); + } + else + { + cl = new java.net.URLClassLoader(url); + } + + _classLoaders.put(classDir, cl); + } + + c = cl.loadClass(className); + } + catch(java.net.MalformedURLException ex) + { + throw new PluginInitializationException("invalid entry point format `" + pluginSpec + "'", ex); + } + catch(java.io.IOException ex) + { + throw new PluginInitializationException("invalid path in entry point `" + pluginSpec + "'", ex); + } + catch(java.lang.ClassNotFoundException ex) + { + // Ignored + } + } + else + { + c = IceInternal.Util.getInstance(_communicator).findClass(className); + } + if(c == null) { - PluginInitializationException e = new PluginInitializationException(); - e.reason = "class " + className + " not found"; - throw e; + throw new PluginInitializationException("class " + className + " not found"); } + java.lang.Object obj = c.newInstance(); try { @@ -315,8 +459,8 @@ public final class PluginManagerI implements PluginManager } catch(ClassCastException ex) { - throw new PluginInitializationException( - "class " + className + " does not implement Ice.PluginFactory", ex); + throw new PluginInitializationException("class " + className + " does not implement Ice.PluginFactory", + ex); } } catch(IllegalAccessException ex) @@ -344,18 +488,40 @@ public final class PluginManagerI implements PluginManager { throw new PluginInitializationException("exception in factory " + className, ex); } - + if(plugin == null) { throw new PluginInitializationException("failure in factory " + className); } - _plugins.put(name, plugin); - _initOrder.add(plugin); + PluginInfo info = new PluginInfo(); + info.name = name; + info.plugin = plugin; + _plugins.add(info); + } + + private Plugin + findPlugin(String name) + { + for(PluginInfo p : _plugins) + { + if(name.equals(p.name)) + { + return p.plugin; + } + } + return null; + } + + static class PluginInfo + { + String name; + Plugin plugin; } private Communicator _communicator; - private java.util.Map<String, Plugin> _plugins = new java.util.HashMap<String, Plugin>(); - private java.util.List<Plugin> _initOrder = new java.util.ArrayList<Plugin>(); + private IceInternal.Instance _instance; + private java.util.List<PluginInfo> _plugins = new java.util.ArrayList<PluginInfo>(); private boolean _initialized; + private java.util.Map<String, ClassLoader> _classLoaders; } diff --git a/java/src/IceBox/ServiceManagerI.java b/java/src/IceBox/ServiceManagerI.java index 8811bb84932..aa066fb2e7e 100644 --- a/java/src/IceBox/ServiceManagerI.java +++ b/java/src/IceBox/ServiceManagerI.java @@ -214,7 +214,6 @@ public class ServiceManagerI extends _ServiceManagerDisp "Added service observer " + _communicator.proxyToString(observer)); } - for(ServiceInfo info: _services) { if(info.status == StatusStarted) @@ -222,7 +221,6 @@ public class ServiceManagerI extends _ServiceManagerDisp activeServices.add(info.name); } } - } } @@ -355,7 +353,7 @@ public class ServiceManagerI extends _ServiceManagerDisp for(StartServiceInfo s : servicesInfo) { - start(s.name, s.className, s.args); + start(s.name, s.className, s.classDir, s.absolutePath, s.args); } // @@ -462,7 +460,7 @@ public class ServiceManagerI extends _ServiceManagerDisp } synchronized private void - start(String service, String className, String[] args) + start(String service, String className, String classDir, boolean absolutePath, String[] args) throws FailureException { // @@ -475,12 +473,74 @@ public class ServiceManagerI extends _ServiceManagerDisp try { - Class<?> c = IceInternal.Util.findClass(className, null); + Class<?> c = null; + + // + // Use a class loader if the user specified a JAR file or class directory. + // + if(classDir != null) + { + try + { + if(!absolutePath) + { + classDir = new java.io.File(System.getProperty("user.dir") + java.io.File.separator + + classDir).getCanonicalPath(); + } + + if(!classDir.endsWith(java.io.File.separator) && !classDir.endsWith(".jar")) + { + classDir += java.io.File.separator; + } + + // + // Reuse an existing class loader if we have already loaded a plug-in with + // the same value for classDir, otherwise create a new one. + // + ClassLoader cl = null; + + if(_classLoaders == null) + { + _classLoaders = new java.util.HashMap<String, ClassLoader>(); + } + else + { + cl = _classLoaders.get(classDir); + } + + if(cl == null) + { + final java.net.URL[] url = new java.net.URL[] { new java.net.URL("file:///" + classDir) }; + + cl = new java.net.URLClassLoader(url); + + _classLoaders.put(classDir, cl); + } + + c = cl.loadClass(className); + } + catch(java.net.MalformedURLException ex) + { + throw new FailureException("ServiceManager: invalid entry point format `" + classDir + "'", ex); + } + catch(java.io.IOException ex) + { + throw new FailureException("ServiceManager: invalid path in plug-in entry point `" + classDir + + "'", ex); + } + catch(java.lang.ClassNotFoundException ex) + { + // Ignored + } + } + else + { + c = IceInternal.Util.findClass(className, null); + } + if(c == null) { - FailureException e = new FailureException(); - e.reason = "ServiceManager: class " + className + " not found"; - throw e; + throw new FailureException("ServiceManager: class " + className + " not found"); } // @@ -893,28 +953,85 @@ public class ServiceManagerI extends _ServiceManagerDisp name = service; // - // Separate the entry point from the arguments. + // We support the following formats: // - int pos = IceUtilInternal.StringUtil.findFirstOf(value, " \t\n"); - if(pos == -1) + // <class-name> [args] + // <jar-file>:<class-name> [args] + // <class-dir>:<class-name> [args] + // "<path with spaces>":<class-name> [args] + // "<path with spaces>:<class-name>" [args] + // + + try { - className = value; - args = new String[0]; + args = IceUtilInternal.Options.split(value); } - else + catch(IceUtilInternal.Options.BadQuote ex) { - className = value.substring(0, pos); - try + throw new FailureException("ServiceManager: invalid arguments for service `" + name + "':\n" + + ex.getMessage()); + } + + assert(args.length > 0); + + final String entryPoint = args[0]; + + final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); + absolutePath = false; + + // + // Find first ':' that isn't part of the file path. + // + int pos = entryPoint.indexOf(':'); + if(isWindows) + { + final String driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if(pos == 1 && entryPoint.length() > 2 && driveLetters.indexOf(entryPoint.charAt(0)) != -1 && + (entryPoint.charAt(2) == '\\' || entryPoint.charAt(2) == '/')) { - args = IceUtilInternal.Options.split(value.substring(pos)); + absolutePath = true; + pos = entryPoint.indexOf(':', pos + 1); } - catch(IceUtilInternal.Options.BadQuote ex) + if(!absolutePath) { - FailureException e = new FailureException(); - e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.toString(); - throw e; + absolutePath = entryPoint.startsWith("\\\\"); } } + else + { + absolutePath = entryPoint.startsWith("/"); + } + + if((pos == -1 && absolutePath) || (pos != -1 && entryPoint.length() <= pos + 1)) + { + // + // Class name is missing. + // + throw new FailureException("ServiceManager: invalid entry point for service `" + name + "':\n" + + entryPoint); + } + + // + // Extract the JAR file or subdirectory, if any. + // + classDir = null; // Path name of JAR file or subdirectory. + + if(pos == -1) + { + className = entryPoint; + } + else + { + classDir = entryPoint.substring(0, pos).trim(); + className = entryPoint.substring(pos + 1).trim(); + } + + // + // Shift the arguments. + // + String[] tmp = new String[args.length - 1]; + System.arraycopy(args, 1, tmp, 0, args.length - 1); + args = tmp; if(serverArgs.length > 0) { @@ -933,6 +1050,8 @@ public class ServiceManagerI extends _ServiceManagerDisp String name; String[] args; String className; + String classDir; + boolean absolutePath; } private Ice.Properties @@ -969,6 +1088,7 @@ public class ServiceManagerI extends _ServiceManagerDisp private java.util.List<ServiceInfo> _services = new java.util.LinkedList<ServiceInfo>(); private boolean _pendingStatusChanges = false; private Ice.Callback _observerCompletedCB; - java.util.HashSet<ServiceObserverPrx> _observers = new java.util.HashSet<ServiceObserverPrx>(); - int _traceServiceObserver = 0; + private java.util.HashSet<ServiceObserverPrx> _observers = new java.util.HashSet<ServiceObserverPrx>(); + private int _traceServiceObserver = 0; + private java.util.Map<String, ClassLoader> _classLoaders; } diff --git a/java/src/IceInternal/Instance.java b/java/src/IceInternal/Instance.java index 7ca90d82144..4f1334be0b8 100644 --- a/java/src/IceInternal/Instance.java +++ b/java/src/IceInternal/Instance.java @@ -684,7 +684,7 @@ public final class Instance EndpointFactory udpEndpointFactory = new UdpEndpointFactory(this); _endpointFactoryManager.add(udpEndpointFactory); - _pluginManager = new Ice.PluginManagerI(communicator); + _pluginManager = new Ice.PluginManagerI(communicator, this); _outgoingConnectionFactory = new OutgoingConnectionFactory(communicator, this); diff --git a/java/src/IceInternal/Util.java b/java/src/IceInternal/Util.java index 6ecc0505a89..f4c383e6388 100644 --- a/java/src/IceInternal/Util.java +++ b/java/src/IceInternal/Util.java @@ -151,7 +151,6 @@ public final class Util private static Class<?> loadClass(String className, ClassLoader cl) - throws LinkageError { if(cl != null) { |