Dr. Stefan Winkler
freier Softwareentwickler und IT-Berater

Say, you want to implement a quick and flexible automation enhancement to one of your eclipse RCP plugins - for example, because you are writing some sort of business application in which you always have to create a few standard structures manually in order to play with it and test it. Here's how you can do it the groovy way:

  • create a new plugin project that depends on all plug-ins you want the automation script to be able to access.
  • download groovy-all-x.y.z.jar from the Groovy homepage and put it into your plug-in's runtime classpath.
  • create an objectContribution like this:
      <objectContribution
            adaptable="false"
            id="myproject.groovyRunner"
            nameFilter="*.groovy"
            objectClass="org.eclipse.core.resources.IFile">
         <action
               class="myproject.automate.RunGroovyAction"
               enablesFor="1"
               id="myproject.groovyRunnerAction"
               label="Execute as Automation Script"
               menubarPath="additions">
         </action>
      </objectContribution>
  • implement the action like this
package myproject.automate;

import java.io.PrintWriter;
import java.io.StringWriter;

import groovy.lang.GroovyClassLoader;

import org.codehaus.groovy.control.ErrorCollector;
import org.codehaus.groovy.control.MultipleCompilationErrorsException;
import org.codehaus.groovy.control.messages.Message;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;

import myproject.MyPlugin;

public class RunGroovyAction implements IObjectActionDelegate {

    /** store the parent shell */
    private Shell shell = null;

    /** store the selected file */
    private IFile file;

    @Override
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        shell = targetPart.getSite().getShell();
    }

    @Override
    public void selectionChanged(IAction action, ISelection selection) {
        file = (IFile) ((IStructuredSelection)selection).getFirstElement();
    }

    @Override
    public void run(IAction action) {
        Assert.isNotNull(shell);
        Assert.isNotNull(file);

        try {
            /* initialize the GroovyClassLoader with the Eclipse class loader */
            GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader());

            /* parse the groovy file */
            Class<?> parsed = loader.parseClass(file.getContents());

            /* cast it to runnable (or whatever you like to implement */
            Class<? extends Runnable> clazz = parsed.asSubclass(Runnable.class);

            /* instantiate and rum */
            Runnable r = clazz.newInstance();
            r.run();
        }
        catch(MultipleCompilationErrorsException e) {
            /* report compilation errors in an error dialog */

            StringWriter messages = new StringWriter();
            PrintWriter printWriter = new PrintWriter(messages);

            ErrorCollector ec = e.getErrorCollector();
            if(ec.hasErrors()) {
                for(Object o : ec.getErrors()) {
                    ((Message) o).write(printWriter);
                    printWriter.append('\n');
                }
            }

            Status status = new Status(IStatus.ERROR, MyPlugin.PLUGIN_ID,
                    messages.toString(), e);

            ErrorDialog.openError(shell, "Compilation errors", messages.toString(), status);
        } catch(Exception e) {
            /* report all other errors here */

            Status status = new Status(IStatus.ERROR, MyPlugin.PLUGIN_ID,
                    "Execution error", e.getCause() == null ? e : e
                            .getCause());

            ErrorDialog.openError(shell, "Error", "Execution error", status);
        }
    }
}

Now you can run your Eclipse application, create a .groovy class (implementing Runnable in the case above) in a file and run it from within your runtime workspace. Happy scripting ...