Adding to the Webstart classpath

What I’ve got at the moment is a simple game which loads pretty much all of the resources from the classpath, including resorces which reference other resources. All is fine and dandy for development as I have a collection of dirs manually added to the classpath where my raw files sit. For webstart these get packed up into jars and all is good. Pretty standard stuff.

Now what I’d like to do is provide this as a webstart app, and then have another person able to add their own resources to it. They’d pick an external dir (say, C:\MyGame\Resources) and ‘somehow’ that dir would be added to my apps classpath and resources could be loaded from it without the game knowing there’s any difference.

I’m slightly lost how to do this, my current thinking would be to provide a custom ClassLoader which would check this new dir manually first, then delagate pretty much everything else to the normal ClassLoader. Is this going to work? Anyone have any suggestions?

I use the following code to add a directory with jars to the classpath. I don’t know if this works with jws though.


public class ClassPathExtender {
 private static final Class[] parameters = new Class[] {URL.class};

 public static void addExtDir(File dir) {
   if (dir.exists() && dir.isDirectory()) {
     File[] jars = dir.listFiles(new FilenameFilter() {
       public boolean accept(File dir, String name) {
         return name.toLowerCase().endsWith(".jar");
       }
    });
    for (int i = 0; i < jars.length; i++) {
      try {
        addFile(jars[i]);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private static void addFile(File f) {
    URL u = f.toURL();
    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;
    try {
      Method method = sysclass.getDeclaredMethod("addURL", parameters);
      method.setAccessible(true);
      method.invoke(sysloader, new Object[] { u });
    } catch (Throwable t) {
      t.printStackTrace();
      throw new IOException("Could not add URL " + u + " to system classloader");
   }
}

There might be some typos in it (typed it over from my laptop :slight_smile:

So…just to check…that adds any arbitrary class accessible via any URL (file, http, etc) using the system classloader, so that you don’t get any problems with classloader-spaces causing class/class compares to fail for identical classes?

If it works…would you mind uploading that as a source file to JGF? Would be nice to have side-by-side with the ClassPath sources that scan the classpath for any class or implementor-of-an-interface.

Yes, I’ve stumbled accross that a couple of times looking for a solution (with slight variations). It’s a tad hacky what with relying on the system classloader to be a URLClassLoader but it does work rather nicely. I’m hoping that the Webstart classloader is also an URLClassLoader as well.

The ‘proper’ solution to what I’m after is supposed to be with a custom ClassLoader which checks my own resource locations. Unfortunatly the delagation method only checks a custom loader after the system classloader has failed to find something. But because an external class gets loaded fine with the system classloader it doesn’t check ‘further down’ the delagation order and so my new loader never even gets a look in. I suspect to do that properly I’d have to re-implement an entire ClassLoader myself (effectivly ignoring the delagation method and going back to Java 1.1 classloader interface) but that’s not something I particularly want to waste time doing.

Seems to, as you never add any additional loaders - you just extend the search paths for the existing one.