How to Dynamically Define a Script's Classpath

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

How to Dynamically Define a Script's Classpath

Azubuko Obele

Is there a standard mechanism for expanding a script's classpath from java code (ie not from inside the script using addClassPath)? I would like to expand the classpath for scripts that act as plugins of sorts. I don't want the user to have to do a bunch of 'addClasspath' statements inside the script itself--instead I'd rather they define the classpath in an XML file. The problem is, there seems to be no good way to expand the script's classpath from within the Java program. So far I have worked out the following code:

        BshClassManager classManager = new BshClassManager();
        NameSpace nameSpace = new NameSpace(classManager, "");
        Interpreter interpreter = new Interpreter();

        // XXX: this is another hack to try and make bsh's dynamic classpath work
        try {
            URLClassLoader classLoader = (URLClassLoader) getScriptClassLoader();
            URL[] classPathUrls = classLoader.getURLs();
            for (int i = 0; i < classPathUrls.length; ++i) {

                // NOTE: for some reason (likely due to Linux URL handling) the addClassPath(URL) methods on linux
                // don't work at all
                if (System.getProperty("").equals("Linux")) {
                    String jarUrlStr = classPathUrls[i].toExternalForm();
                    jarUrlStr = jarUrlStr.substring(6);
                    if (log.isDebugEnabled()) {
                        log.debug("Adding Beanshell ClassPath File: " + jarUrlStr);

                    interpreter.eval("addClassPath(\"" + jarUrlStr + "\")");

                } else {
                    if (log.isDebugEnabled()) {
                        log.debug("Adding Beanshell Classpath URL: " + classPathUrls[i]);

        } catch (EvalError ee) {
            throw new ScriptingException("failed to load script classpath", ee);
        } catch (IOException ioe) {
            throw new ScriptingException("failed to load script classpath", ioe);

There are a few problems with this code:

(1) It's not very pretty.

(2) While it works fine on Windows, it doesn't work on Linux. After doing a bit of investigation I think the problem is related to the fact that objects (returned by File.toURL() ) on Linux get converted to 'file:/' URLS (1 slash) instead of 'file:///' URLS (3 slashses). This seems to be a known problem with Linux and File.toURL() . The problem is the File.toURL() which seems to be very broken and soon to be deprecated. (Google around for the many problems with the File.toURL method).

For reference, I'm using jdk 1.4.2 and beanshell 2.0b4.

So, has anybody figured out a good way for extending a script's classpath from Java code?