// ********************************************************************** // // Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** package Ice; public final class PluginManagerI implements PluginManager { private static String _kindOfObject = "plugin"; public synchronized void initializePlugins() { if(_initialized) { InitializationException ex = new InitializationException(); ex.reason = "plug-ins already initialized"; throw ex; } // // Invoke initialize() on the plug-ins, in the order they were loaded. // java.util.List initializedPlugins = new java.util.ArrayList(); try { for(PluginInfo p : _plugins) { p.plugin.initialize(); initializedPlugins.add(p.plugin); } } catch(RuntimeException ex) { // // Destroy the plug-ins that have been successfully initialized, in the // reverse order. // java.util.ListIterator i = initializedPlugins.listIterator(initializedPlugins.size()); while(i.hasPrevious()) { Plugin p = i.previous(); try { p.destroy(); } catch(RuntimeException e) { // Ignore. } } throw ex; } _initialized = true; } public synchronized String[] getPlugins() { java.util.ArrayList names = new java.util.ArrayList(); for(PluginInfo p : _plugins) { names.add(p.name); } return names.toArray(new String[0]); } public synchronized Plugin getPlugin(String name) { if(_communicator == null) { throw new CommunicatorDestroyedException(); } Plugin p = findPlugin(name); if(p != null) { return p; } NotRegisteredException ex = new NotRegisteredException(); ex.id = name; ex.kindOfObject = _kindOfObject; throw ex; } public synchronized void addPlugin(String name, Plugin plugin) { if(_communicator == null) { throw new CommunicatorDestroyedException(); } if(findPlugin(name) != null) { AlreadyRegisteredException ex = new AlreadyRegisteredException(); ex.id = name; ex.kindOfObject = _kindOfObject; throw ex; } PluginInfo info = new PluginInfo(); info.name = name; info.plugin = plugin; _plugins.add(info); } public synchronized void destroy() { if(_communicator != null) { if(_initialized) { java.util.ListIterator i = _plugins.listIterator(_plugins.size()); while(i.hasPrevious()) { PluginInfo p = i.previous(); try { p.plugin.destroy(); } catch(RuntimeException ex) { 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, IceInternal.Instance instance) { _communicator = communicator; _instance = instance; _initialized = false; } public void loadPlugins(StringSeqHolder cmdArgs) { assert(_communicator != null); // // Load and initialize the plug-ins defined in the property set // with the prefix "Ice.Plugin.". These properties should // have the following format: // // Ice.Plugin.name[.]=entry_point [args] // // If the Ice.PluginLoadOrder property is defined, load the // specified plug-ins in the specified order, then load any // remaining plug-ins. // final String prefix = "Ice.Plugin."; Properties properties = _communicator.getProperties(); java.util.Map plugins = properties.getPropertiesForPrefix(prefix); final String[] loadOrder = properties.getPropertyAsList("Ice.PluginLoadOrder"); for(String name : loadOrder) { if(findPlugin(name) != null) { PluginInitializationException ex = new PluginInitializationException(); ex.reason = "plug-in `" + name + "' already loaded"; throw ex; } String key = "Ice.Plugin." + name + ".java"; boolean hasKey = plugins.containsKey(key); if(hasKey) { plugins.remove("Ice.Plugin." + name); } else { key = "Ice.Plugin." + name; hasKey = plugins.containsKey(key); } if(hasKey) { final String value = plugins.get(key); loadPlugin(name, value, cmdArgs); plugins.remove(key); } else { PluginInitializationException ex = new PluginInitializationException(); ex.reason = "plug-in `" + name + "' not defined"; throw ex; } } // // Load any remaining plug-ins that weren't specified in PluginLoadOrder. // while(!plugins.isEmpty()) { java.util.Iterator > p = plugins.entrySet().iterator(); java.util.Map.Entry entry = p.next(); String name = entry.getKey().substring(prefix.length()); int dotPos = name.lastIndexOf('.'); if(dotPos != -1) { String suffix = name.substring(dotPos + 1); if(suffix.equals("cpp") || suffix.equals("clr")) { // // Ignored // p.remove(); } else if(suffix.equals("java")) { 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 { // // Name is just a regular name that happens to contain a dot // dotPos = -1; } } if(dotPos == -1) { // // Is there a .java entry? // String value = entry.getValue(); p.remove(); String javaValue = plugins.remove("Ice.Plugin." + name + ".java"); if(javaValue != null) { value = javaValue; } loadPlugin(name, value, cmdArgs); } } } private void loadPlugin(String name, String pluginSpec, StringSeqHolder cmdArgs) { assert(_communicator != null); // // We support the following formats: // // [args] // : [args] // : [args] // "": [args] // ":" [args] // String[] args; try { args = IceUtilInternal.Options.split(pluginSpec); } 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)) { // // 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 = 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; // // 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. // Properties properties = _communicator.getProperties(); args = properties.parseCommandLineOptions(name, args); cmdArgs.value = properties.parseCommandLineOptions(name, cmdArgs.value); // // Instantiate the class. // PluginFactory pluginFactory = null; try { 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(); } 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) { throw new PluginInitializationException("class " + className + " not found"); } java.lang.Object obj = c.newInstance(); try { pluginFactory = (PluginFactory)obj; } catch(ClassCastException ex) { throw new PluginInitializationException("class " + className + " does not implement Ice.PluginFactory", ex); } } catch(IllegalAccessException ex) { throw new PluginInitializationException("unable to access default constructor in class " + className, ex); } catch(InstantiationException ex) { throw new PluginInitializationException("unable to instantiate class " + className, ex); } // // Invoke the factory. // Plugin plugin = null; try { plugin = pluginFactory.create(_communicator, name, args); } catch(PluginInitializationException ex) { throw ex; } catch(Throwable ex) { throw new PluginInitializationException("exception in factory " + className, ex); } if(plugin == null) { throw new PluginInitializationException("failure in factory " + className); } 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 IceInternal.Instance _instance; private java.util.List _plugins = new java.util.ArrayList(); private boolean _initialized; private java.util.Map _classLoaders; }