2009-04-07 68 views
2

我正在尝试扩展一个Eclipse代码生成器(用于从Hibernate VO生成DTO) - 并且它将Groovy用作其模板系统。如何设置嵌入式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(); 

现在,这工作得很好,直到遇到不直接在项目中的对象的引用。在脚本中,它遍历它正在处理的Class的属性 - 当它执行此操作时,Groovy会查看所有方法,以及何时无法为其中一个方法参数找到类定义,它会突出显示。在这种情况下,当它发现任何对Hibernate的引用时会死亡,但我相信它会带来更多的麻烦。它不需要对他们做任何事情,但如果不知道他们显然是什么,它就无法生存。

Script似乎没有一个类加载器,我可以提供任何类路径信息,所以我尝试将它提供给GroovyShell - 没有区别。

解决这个问题的正确方法是什么,以便Groovy解释器可以找到我的项目引用Jars?

回答

2

我有这个确切的问题并解决它通过创建我自己的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); 
+0

可以直接使用.groovy文件做类似的事情吗? (即不要先编译它们) – hithwen 2012-03-06 18:18:44

0

我有同样的问题,试图自动运行Gant脚本。我找到了解决办法是:

  1. 复制GANT-starter.conf(或 Groovy的starter.conf如果它只是 常规)从$ GROOVY_HOME/conf目录到你 自己的目录;

  2. 添加 “负载[目录]” 或 “负载[罐子]” 有,如在 Javadoc中描述 org.codehaus.groovy.tools.LoaderConfiguration, 在Groovy源分布实测值;

  3. 开始常规组 groovy.starter.conf.override系统 属性到该文件的名称, 像 -Dgroovy.starter.conf.override = [文件名]

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"); 
    } 
}