2009-04-07 86 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"); 
    } 
}