Link to external jars in plugin? [message #1405200] |
Wed, 06 August 2014 20:36  |
Eclipse User |
|
|
|
I'm trying to make my plugin working without shipping the system jfxswt.jar, which provides JavaFX integration into SWT.
Currently it only works if I put the jfxswt.jar into my plugin. Because the jfxswt.jar depends on SWT at runtime, it'd fail to find SWT classes when jfxswt.jar is inside system classpath or injected through adding URLClassLoader.addURL.
I don't really want to create a normal ClassLoaderHook like e(fx)clipse does, because that would require an additional bundle as osgi.framework.extension and installed in eclipse location. Do I have other choices? Can I just declare an external jar to be part of my plugin without actually including it?
|
|
|
Re: Link to external jars in plugin? [message #1405221 is a reply to message #1405200] |
Wed, 06 August 2014 21:45   |
Eclipse User |
|
|
|
Answering my own question. I got it work by hacking internal fields 
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.ZipBundleFile;
@SuppressWarnings("restriction")
public final class Internals
{
public static void moduleClassLoader_addClasspathEntry(Class<?> klass, File jarFile)
{
try
{
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) klass.getClassLoader();
ClasspathManager classpathManager = moduleClassLoader.getClasspathManager();
// Get Configuration
Method getConfigurationMethod = ModuleClassLoader.class.getDeclaredMethod("getConfiguration");
getConfigurationMethod.setAccessible(true);
EquinoxConfiguration config = (EquinoxConfiguration) getConfigurationMethod.invoke(moduleClassLoader);
// Get ClasspathManager.entries
Field entriesField = ClasspathManager.class.getDeclaredField("entries");
entriesField.setAccessible(true);
ClasspathEntry[] oldEntries = (ClasspathEntry[]) entriesField.get(classpathManager);
// Make ClasspathManager.entries writable (it's final field!)
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(entriesField, entriesField.getModifiers() & ~Modifier.FINAL);
// Create ClasspathEntry for the given jarFile
BundleFile jarBundleFile = new ZipBundleFile(jarFile, null, null, config.getDebug());
ClasspathEntry jarEntry = new ClasspathEntry(jarBundleFile, oldEntries[0].getDomain(), classpathManager.getGeneration());
// Prepare new entries
ClasspathEntry[] newEntries = new ClasspathEntry[oldEntries.length + 1];
System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
newEntries[oldEntries.length] = jarEntry;
// Set new entries to replace the old one
entriesField.set(classpathManager, newEntries);
System.out.println("added classpath: " + jarFile);
}
catch (IOException | ReflectiveOperationException e)
{
e.printStackTrace();
}
}
}
And calling it in RCP Application like: static
{
Internals.moduleClassLoader_addClasspathEntry(Activator.class,
Paths.get(System.getProperty("java.home"), "lib", "jfxswt.jar").toFile());
}
Still I hope there is some official way to do that......
[Updated on: Wed, 06 August 2014 21:52] by Moderator Report message to a moderator
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03363 seconds