summaryrefslogtreecommitdiff
path: root/java/src/Ice/PluginManagerI.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/Ice/PluginManagerI.java')
-rw-r--r--java/src/Ice/PluginManagerI.java248
1 files changed, 207 insertions, 41 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;
}