Sunday, July 8, 2007

Eclipse plug-ins and JSR-223

Recently I was trying to bind the eclipse plug-in world with JSR-223 and Groovy via javax.script API for my GSoC project. Here's how it turned out.

First I need to have a class that deals with all that javax.script stuff: let there be ScriptingExecutor. Its functionality isn't very advanced - it just delegates the calls to the scripting API and maintains several fields for holding the state of the script. STOP! Why would I need to keep track of the state at all? The problem is that not all the scripting languages with the same semantics/features.

Let's see the example: an action facade and a script that implements this action. I'm using the Expando object to create a class with the same methods as for the action: run(IAction action), selectionChanged(IAction action, ISelection selection), dispose(). The reason why i would like to pass the new object back to the plug-in is that when a selection is changes I would like to save the reference for further processing in the run(IAction) method. The script below has a visibility problem and cannot use def selection to save the state.

def selection

def run(action){
println "selection = ${selection}" // this won't work!!!

def selection(action, selection){
this.selection = selection

The Groovy User Manual says:
Executing this code you get an exception talking about a missing property or field.
The only things the method has access to are:
* the binding,
* attributes defined by the base class, and
* the dynamic properties defined by the MetaClass (explanations for these will follow).
So I decided to use Expando as a base class for saving the state. Simple.

Next, there are 2 options of delegating the plug-in extension to the script object:

  1. Using the invokeMethod/invokeFunction methods of the javax.script.Invocable interfaces. These can be used just for simply calling the functions from the evaluated script. or...

  2. Using getInterface(Class clazz) to create an object that would implement the required interface, of instance IActionDelegate.

I'm not sure which option is really better so I'm using the first one for now.

Next, I should try to implement several facades and scripts for the extensions, so that I could see the common parts and unify them in one. Implementing a facade for every single extension does not seem to be very relevant, perhaps the getInterface(Class clazz) method will help to skip that... Or I will need some sort of Proxy solution to skip all the facades.

Also I'm referencing Eclipse Monkey project as an inspiration. The reason is that for smoothing the script development a set of predefined variables could be very handy, so the user could use them out of the box. And that is what Eclipse Monkey does: it exposes some internal object into the script context so that a script contributor could use them.

1 comment:

Toomas Römer said...

Lucky you. Caucho's PHP's JSR-223 has invokeMethod methods empty ;). Everything has to be done manually.

Disqus for Code Impossible