简体   繁体   English

如何设置嵌入式Groovy脚本的类路径?

[英]How do I set an embedded Groovy scripts classpath?

I am trying to extend an Eclipse code builder (for generating DTOs from Hibernate VOs) - and it uses Groovy for its template system. 我正在尝试扩展Eclipse代码构建器(用于从Hibernate VO生成DTO),并且它将Groovy用于其模板系统。

The code it uses to create the groovy Script is a little weird (not what I see in the Groovy docs) but it works, mostly: 它用来创建groovy脚本的代码有点奇怪(不是我在Groovy文档中看到的),但是它可以正常工作,主要是:

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

Then, later: 然后,稍后:

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

Now, this works just fine, until it hits a reference to an object that is not directly in the project. 现在,这很好用,直到它找到对不直接在项目中的对象的引用。 In the script, it iterates through the properties of the Class that it is processing - when it does this, Groovy looks at all of the methods and when it can't find a Class definition for one of the method parameters, it craps out. 在脚本中,它遍历正在处理的Class的属性-当执行此操作时,Groovy会查看所有方法,而当它找不到方法参数之一的Class定义时,它将退出。 In this case, it's dying when it finds any references to Hibernate, but I'm sure it will crap out with a lot more. 在这种情况下,当它找到任何对Hibernate的引用时,它就死了,但是我敢肯定,它将提供更多的东西。 It doesn't need to do anything to them, but it can't live without knowing what they are apparently. 它不需要对他们做任何事情,但是如果不知道它们的表面情况就无法生存。

Script doesn't appear to have a classloader that I can supply any classpath info, so I tried providing it to the GroovyShell - no difference. 脚本似乎没有可提供任何类路径信息的类加载器,因此我尝试将其提供给GroovyShell-没什么区别。

What's the proper way to fix this so that the Groovy interpreter can find my projects referenced Jars? 解决此问题的适当方法是什么,以便Groovy解释器可以找到引用Jars的项目?

The same as @James can be done without using reflection, loading all jar files from a certain folder: 无需使用反射即可完成@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" );
    }
}

I had this exact problem and solved it by creating my own URLClassLoader, and using reflection to call a protected method to add a new path to the ClassPath 我遇到了这个确切的问题,并通过创建自己的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 );

I'm having the same problem trying to automate Gant scripts running. 我在尝试自动运行Gant脚本时遇到了同样的问题。 The solution I found is: 我找到的解决方案是:

  1. copy gant-starter.conf (or groovy-starter.conf if it's just groovy) from $GROOVY_HOME/conf to your own dir; 从$ GROOVY_HOME / conf复制gant-starter.conf(或groovy-starter.conf)到您自己的目录;

  2. add "load [directory]" or "load [jar]" there, as described in javadocs to org.codehaus.groovy.tools.LoaderConfiguration, found in Groovy source distribution; 按照javadocs中的描述,在Groovy源代码分发中的org.codehaus.groovy.tools.LoaderConfiguration中添加“加载[目录]”或“加载[jar]”;

  3. before starting groovy set groovy.starter.conf.override system property to the name of that file, like -Dgroovy.starter.conf.override=[filename] 在开始groovy之前,请将groovy.starter.conf.override系统属性设置为该文件的名称,例如-Dgroovy.starter.conf.override = [filename]

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

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