summaryrefslogtreecommitdiff
path: root/java/src/IceBox/ServiceManagerI.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/IceBox/ServiceManagerI.java')
-rw-r--r--java/src/IceBox/ServiceManagerI.java166
1 files changed, 143 insertions, 23 deletions
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;
}