简体   繁体   English

GroovyScriptEngine无法加载正在运行的groovy脚本的导入

[英]GroovyScriptEngine fails to load imports of running groovy script

Background : 背景 :

I started playing with Groovy recently and am trying to embed a groovy script engine in an eclipse plugin to let my customers develop their own GUI extensions inside my eclipse-based product. 我最近开始玩Groovy,并试图将groovy脚本引擎嵌入eclipse插件中,以使我的客户在基于eclipse的产品中开发自己的GUI扩展。 This is very similar to the success story published on codehaus's website. 这与codehaus网站上发布的成功故事非常相似。

Problem 问题

The groovy script (let's call it "main_eclipse.groovy") run from the eclipse plugin by a GroovyScriptEngine throws when trying to load a groovy class ("SwtGuiBuilder"), with the following error : 尝试加载groovy类(“ SwtGuiBuilder”)时,由GroovyScriptEngine从eclipse插件运行的groovy脚本(我们称其为“ main_eclipse.groovy”),具有以下错误:

BUG! BUG! Queuing new source whilst already iterating. 在已经迭代的同时排队新资源。 Queued source is 'file:/home/nicolas/workspace/groovy-test/src/gui/SwtGuiBuilder.groovy' 排队的源是“文件:/home/nicolas/workspace/groovy-test/src/gui/SwtGuiBuilder.groovy”

Question

Did anyone run into the same problem ? 有人遇到过同样的问题吗? How can it be fixed ? 如何解决? Any help will be highly appreciated ! 任何帮助将不胜感激!

Some observations : 一些观察:

  • When using the groovy interpreter instead of a GroovyScriptEngine java object, I have no problem using my SwtGuiBuilder class (see script "main_groovy" here below). 当使用groovy解释器而不是GroovyScriptEngine java对象时,使用我的SwtGuiBuilder类没有问题(请参见下面的脚本“ main_groovy”)。

  • My problem does not seem to be a classpath issue, since the file containing my SwtGuiBuilder class is mentioned in the thrown exception. 我的问题似乎不是类路径问题,因为在抛出的异常中提到了包含Sw​​tGuiBuilder类的文件。

  • The error message is mentioned in two reported groovy bugs, GRECLIPSE-429 and GRECLIPSE-1037. 在两个报告的常规错误GRECLIPSE-429和GRECLIPSE-1037中提到了错误消息。 I did not fully get the technicals details, but those bugs seemed to be related to performance issues when loading lots of classes, which is not relevant in my situation... 我没有完全了解技术细节,但是这些错误似乎与加载许多类时的性能问题有关,这与我的情况无关。

Details 细节

SampleView.java SampleView.java

public class SampleView
{
public SampleView() { super(); }

public void createPartControl(Composite parent) 
{
    String    groovyScript = null;
    String [] groovyPath   = null;

    boolean shall_exit = false;
    do
    {      // ask user for params
        GroovyLocationDialog groovyLocationDialog= new GroovyLocationDialog(parent.getShell() );
        int return_code = groovyLocationDialog.open();
        if ( return_code != Window.OK )
            shall_exit = true;
        else 
        {
            groovyScript= groovyLocationDialog.getInputScriptName();
            groovyPath  = groovyLocationDialog.getInputScriptPath();

            // run it
            ScriptConnector scriptConnector = new ScriptConnector(parent);
            try                 { scriptConnector.runGuiComponentScript( groovyPath, groovyScript); }
            catch (Exception e) { e.printStackTrace(); }
            System.out.println("script finished");
        }
    }
    while ( ! shall_exit );
}

ScriptConnector.java ScriptConnector.java

public class ScriptConnector
{
    private String[]  roots;
    private Composite window;
    private Binding   binding;

    public ScriptConnector( Composite window )
    {
         this.window    = window;
         Binding  scriptenv = new Binding();    // A new Binding is created ...
         scriptenv.setVariable("SDE", this); 
         scriptenv.setVariable("WINDOW", this.window); // ref to current window

         this.binding = scriptenv;
    }

    public void runGuiComponentScript(final String[] groovyPath, final String scriptName) 
    {
        GroovyScriptEngine gse = null;
        this.roots     = groovyPath;
        try 
        {
            // instanciating the script engine with current classpath
            gse = new GroovyScriptEngine( roots, this.getClass().getClassLoader() );
            gse.run(scriptName, binding);      // ... and run specified script
        }
        catch (Exception e) { e.printStackTrace(); }
        catch (Throwable t) { t.printStackTrace(); }
    }
}

main_eclipse.groovy main_eclipse.groovy

package launcher;

import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.*
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.RowLayout as Layout

// This import will fail...
import gui.SwtGuiBuilder;


WINDOW.layout = new Layout(SWT.VERTICAL);
def builder = new SwtGuiBuilder(WINDOW);
builder.Label ( style=SWT.NONE, text = 'Simple demo of Groovy and SWT')
builder.Button( style=SWT.PUSH, text = 'Click me' , action = { println "Click !" } )

SwtGuiBuilder.groovy SwtGuiBuilder.groovy

package gui;

import org.eclipse.swt.events.*
import org.eclipse.swt.widgets.Button
import org.eclipse.swt.widgets.Composite
import org.eclipse.swt.widgets.Label


class SwtGuiBuilder
{
    private Composite _parent

    public SwtGuiBuilder(Composite parent) { _parent = parent }

    public void Button( style = SWT.PUSH, text= null, action = null )
    {
        def btn = new Button(_parent, style)
        if ( text != null )
            btn.text = text
        if (action != null)
            btn.addSelectionListener( new SelectionAdapter() { void widgetSelected( SelectionEvent event ) { action(); } } );
    }

    public void Label( style = SWT.NONE, text = '' )
    {
        def lbl = new Label(_parent, style)
        lbl.text = text
    }
}

main_groovy.groovy main_groovy.groovy

package launcher;

import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.*
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.RowLayout as Layout

// ... But this import is handled properly !
import gui.SwtGuiBuilder;

def display = new Display()
def WINDOW = new Shell(display)
WINDOW.text = 'Groovy / SWT Test';

WINDOW.layout = new Layout(SWT.VERTICAL);
def builder = new SwtGuiBuilder(WINDOW);
builder.Label ( style=SWT.NONE, text = 'Simple demo of Groovy and SWT')
builder.Button( style=SWT.PUSH, text = 'Click me' , action = { println "Ya clicked me !" } )

WINDOW.pack();
WINDOW.open();

while (!WINDOW.disposed) {
    if (!WINDOW.display.readAndDispatch())
        WINDOW.display.sleep();
}

Stack trace 堆栈跟踪

BUG! BUG! Queuing new source whilst already iterating. 在已经迭代的同时排队新资源。 Queued source is 'file:/home/nicolas/workspace/groovy-test/src/gui/SwtGuiBuilder.groovy' at org.codehaus.groovy.control.CompilationUnit.addSource(CompilationUnit.java:460) at org.codehaus.groovy.control.CompilationUnit.addSource(CompilationUnit.java:433) at groovy.util.GroovyScriptEngine$ScriptClassLoader$3.findClassNode(GroovyScriptEngine.java:195) at org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:124) at org.codehaus.groovy.control.ResolveVisitor.resolveToOuter(ResolveVisitor.java:863) at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:377) at org.codehaus.groovy.control.ResolveVisitor.visitClass(ResolveVisitor.java:1407) at org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:202) at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:713) at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:1015) at org.codehaus.groovy.control.CompilationUnit.doPha 排队的源是org.codehaus.groovy.control.CompilationUnit.addSource(CompilationUnit.java:460)的``file:/home/nicolas/workspace/groovy-test/src/gui/SwtGuiBuilder.groovy'' groovy.util.GroovyScriptEngine $ ScriptClassLoader $ 3.findClassNode(GroovyScriptEngine.java:195)的org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:124)的.control.CompilationUnit.addSource(CompilationUnit.java:433)在org.codehaus.groovy.control.ResolveVisitor.resolveToOuter(ResolveVisitor.java:863)在org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:377)在org.codehaus.groovy.control.ResolveVisitor.visitClass (ResolveVisitor.java:1407)在org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:202)在org.codehaus.groovy.control.CompilationUnit $ 1.call(CompilationUnit.java:713)在org.codehaus org.codehaus.groovy.control.CompilationUnit.doPha上的.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:1015) seOperation(CompilationUnit.java:647) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:596) at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:279) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:258) at groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:247) at groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:229) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:244) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:202) at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:514) at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:564) at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551) groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:279)上org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:596)上的seOperation(CompilationUnit.java:647)在groovy.lang.GroovyClassLoader.parseClass上(GroovyClassLoader.java:258)在groovy.util.GroovyScriptEngine $ ScriptClassLoader.doParseClass(GroovyScriptEngine.java:247)在groovy.util.GroovyScriptEngine $ ScriptClassLoader.parseClass(GroovyScriptEngine.java:229)在groovy.lang.GroovyClass在groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:202)处在Groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:514)在groovy.util.GroovyScriptEngine.Engine Script(Groovy )在groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)

My configuration : 我的配置:

  • Linux Ubuntu 14.04 x86 Linux Ubuntu 14.04 x86

  • Groovy Version: 2.3.2 Groovy版本:2.3.2

  • JVM: 1.7.0_55 的JVM:1.7.0_55

  • Eclipse Kepler SR2 - Build 20140224-0627 Eclipse Kepler SR2-内部版本20140224-0627

  • Eclipse Groovy plugin v2.0.7 Eclipse Groovy插件v2.0.7

Instead of GroovyScriptEngine, I've used the GroovyShell class (groovy code below but easy enough to change back to java), CompilerConfiguration allows you to specify the classpath. 我没有使用GroovyShell类(下面的Groovy代码,但是很容易更改回Java),而是使用GroovyShell类,CompilerConfiguration允许您指定类路径。

    def config = new CompilerConfiguration(classpath: classpath)
    def binding = new Binding()

    def result = new GroovyShell(binding, config).evaluate("""
def foo='bar'
""")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM