3

(Hibernate VO から DTO を生成するための) Eclipse コード ビルダーを拡張しようとしていますが、テンプレート システムに Groovy を使用しています。

groovy スクリプトを作成するために使用するコードは少し奇妙です (Groovy ドキュメントにあるものとは異なります) が、ほとんどの場合は機能します。

GroovyShell shell = new GroovyShell();
script = shell.parse(source);

じゃあ後で:

Binding binding = (bindings == null ? new Binding() : new Binding(bindings));
Script scriptInstance = InvokerHelper.createScript(script.getClass(), binding);
scriptInstance.setProperty("out", out);
scriptInstance.run();
out.flush();

これで、プロジェクトに直接含まれていないオブジェクトへの参照に到達するまで、これは問題なく機能します。スクリプトでは、処理しているクラスのプロパティを反復処理します。これを行うと、Groovy はすべてのメソッドを調べ、メソッド パラメーターの 1 つに対するクラス定義が見つからない場合は失敗します。この場合、Hibernate への参照を見つけると死んでしまいますが、もっと多くのことで失敗すると確信しています。彼らに何もする必要はありませんが、彼らが何であるかを知らずに生きることはできません.

スクリプトには、クラスパス情報を提供できるクラスローダーがないように見えるため、それをGroovyShellに提供しようとしました-違いはありません。

Groovy インタープリターが Jars を参照している私のプロジェクトを見つけられるように、これを修正する適切な方法は何ですか?

4

3 に答える 3

3

この正確な問題があり、独自の URLClassLoader を作成し、リフレクションを使用して保護されたメソッドを呼び出して ClassPath に新しいパスを追加することで解決しました

// Specify the path you want to add
URL url = new URL("file://path/to/classes/here");

// Create a new class loader as a child of the default system class loader
ClassLoader loader = new URLClassLoader(System.getClass().getClassLoader()); 

// Get the AddURL method and call it
Method method = URLClassLoader.class.getDeclaredMethod("addURL",new Class[]{URL.class});
method.setAccessible(true);
method.invoke(loader,new Object[]{ url });

GroovyShell shell = new GroovyShell( loader );
于 2009-04-08T04:41:43.990 に答える
2

@James と同じことは、特定のフォルダーからすべての jar ファイルをロードして、リフレクションを使用せずに行うことができます。

URLClassLoader classLoader = new URLClassLoader( getExtraJarUrls(), getClass().getClassLoader() );
GroovyShell shell = new GroovyShell( classLoader, binding, compilerConfiguration );


private URL[] getExtraJarUrls() throws MalformedURLException
{
    logger.debug( "Loading extra jars from {}", EXTRA_JARS_DIR.getAbsolutePath() );
    URL[] result;
    File[] files = EXTRA_JARS_DIR.listFiles( new JarFilenameFilter() );
    if (files != null)
    {
        List<URL> urls = new ArrayList<URL>( files.length );
        for (File file : files)
        {
            urls.add( file.toURI().toURL() );
        }
        result = urls.toArray( new URL[urls.size()] );
    }
    else
    {
        result = new URL[0];
    }
    logger.debug( "Adding URLs to classloader: {}", Arrays.toString( result ) );
    return result;
}

private static class JarFilenameFilter implements FilenameFilter
{
    public boolean accept( File dir, String name )
    {
        return name.endsWith( ".jar" );
    }
}
于 2012-09-25T12:59:26.280 に答える
1

Gant スクリプトの実行を自動化しようとして同じ問題が発生しています。私が見つけた解決策は次のとおりです。

  1. $GROOVY_HOME/conf から自分のディレクトリに gant-starter.conf (または単に groovy の場合は groovy-starter.conf) をコピーします。

  2. Groovy ソース配布にある org.codehaus.groovy.tools.LoaderConfiguration の javadoc で説明されているように、そこに「load [directory]」または「load [jar]」を追加します。

  3. groovy を開始する前に、groovy.starter.conf.override システム プロパティをそのファイルの名前に設定します (例: -Dgroovy.starter.conf.override=[filename])。

于 2009-04-16T00:11:55.030 に答える