Our BeanShell interpreter is already capable of calling java code, so we only need to make sure that its classloader will have access to all desired resources.
Read all tutorials from this series.
Source code for this tutorial is available on github as a single zip archive, as a Team Project Set or you can browse the files online.
Step 1: Access java classes from eclipse
Our BeanShell interpreter already accepts calls to JRE classes like
java.lang.System.out.println("Hello world");
However if we try to access eclipse classes likeorg.eclipse.jface.resource.JFaceColors Sourced file: inline evaluation of: ``org.eclipse.jface.resource.JFaceColors;'' : Class or variable not found: org.eclipse.jface.resource.JFaceColorsWe get an exception indicating that the class cannot be found. This is a classloader issue as the interpreter uses the bundle classloader from our org.eclipse.ease.lang.beanshell bundle. We could add dependencies to jface to solve the problem, but how would we introduce dependencies to all plug-ins that might be used by a customer?
Fortunately eclipse has a solution for this. We may allow plug-ins to access classes from all exported packages out there without adding a dedicated dependency by defining
Eclipse-BuddyPolicy: globalin the MANIFEST.MF file. This comes with a penalty on class loading performance but allows to access all available classes.
Add this setting to the manifest of org.eclipse.ease.lang.beanshell. Afterwards switch to the BeanShellEngine and add following line to setupEngine():
fInterpreter.setClassLoader(getClass().getClassLoader());This line changes the classloader of the BeanShell with the one from the org.eclipse.ease.lang.beanshell bundle.
Now go and try to load some eclipse classes:
org.eclipse.jface.resource.JFaceColors Class Identifier: org.eclipse.jface.resource.JFaceColors
Step 2: Load classes from external URLs
EASE allows to register external jar files and make them available to scripting. This mechanism is provided by a module - a concept we will introduce in the next tutorial. For now we will make all necessary preparations. EASE provides a generic classloader with all necessary functionality. Go to your BeanShellEngine and modify the code as follows:
public class BeanShellEngine extends AbstractScriptEngine { private DelegatingJarClassLoader fClassLoader; @Override protected boolean setupEngine() { fInterpreter = new Interpreter(); fClassLoader = new DelegatingJarClassLoader(getClass().getClassLoader()); fInterpreter.setClassLoader(fClassLoader); [...] } @Override public void registerJar(final URL url) { if (fClassLoader != null) fClassLoader.registerURL(url); } }The DelegatingClassLoader will take care of registered URLs. For everything else its parent classloader will be used. We cannot test this currently, so you need to trust me on this until the next tutorial.
No comments:
Post a Comment