Maria
Maria

Reputation: 5604

Adding jars to an Eclipse plugin at runtime

I'm working on a Eclipse plugin that needs classes which are not known at compile time. The classes get sent over the network in jar files. I would like to dynamically load those classes at runtime.

I've tried the approach listed here: http://blog.imaginea.com/making-applications-work-together-in-eclipse/

Unfortunately it doesn't have the desired effect. While the classes do get loaded, I can't use them outside the function where I loaded them. I'm guessing it has something to do with using different class loaders.

Any help is appreciated. Even if you tell me, that it is not possible, so I know I don't have to look any further.

Upvotes: 7

Views: 3629

Answers (2)

Andrew Niefer
Andrew Niefer

Reputation: 4309

If you make those jars into OSGi bundles (ie, give them a MANIFEST.MF) then you can install them into the OSGi runtime dynamically.

If you add a bundle activator to your plugin, then you can store the org.osgi.framework.BundleContext and then you can do:

  Bundle [] newBundle = new Bundle[] { bundleContext.install(location, newJarInputStream) };
  packageAdmin.refreshPackages( newBundle );
  packageAdmin.resolveBundles( newBundle); 

packageAdmin is an instance of org.osgi.service.packageAdmin.PackageAdmin which is a service you can acquire with BundleContext#getService

The new jars can be entire bundles in their own right, or they can also be bundle fragments that have your plugin as their host. If they are fragments of your bundle then the your bundle (BundleContext#getBundle()) will need to be included in the array passed to refreshPackages and resolveBundles.

(EDIT classloading) Class.forName from your plugin code will only find classes in the newly installed bundles if your plugin has dependencies that will be satisfied by the new bundles once they are resolved.

  • One way to do this would an optional Import-Package in your plugin's manifest. In this case your plugin will need to be included in the array passed to refreshPackages.
  • Another option would be to use a DynamicImport-Package statement in your plugin's manifest. Dynamic imports are resolved during class loading

Another option is to use Bundle.loadClass (instead of Class.forName)on the bundle objects for your newly installed bundles. This uses the new bundle's classloader so your plugin itself does not need to have a dependency on the new bundles.

Upvotes: 5

Will
Will

Reputation: 6286

I recently did this for a plugin to eclipse:

Here's the salient code

URL[] urls = new URL[]{ new URL("jar", "", "file:" + jarFile.getAbsolutePath() + "!/")};
URLClassLoader cl = URLClassLoader.newInstance(urls, this.getClass().getClassLoader());
Class<?> loadedClass = cl.loadClass("com.whatever.SomeClass");

Upvotes: 2

Related Questions