2011-06-23 110 views
6

我正在重構Java應用程序以使用OSGi。該應用程序的一個功能是使用javax.tools.JavaCompiler進行即時Java編譯。在原始應用程序中,此過程通過向編譯器提供現有的類路徑來工作,就像這樣。在OSGi包中使用JavaCompiler

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
String[] options = {"-classpath", System.getProperty("java.class.path")}; 
DiagnosticListener<JavaFileObject> listener = new DiagnosticListener<JavaFileObject>() {...}; 
StandardJavaFileManager fileManager = compiler.getStandardFileManager(listener, null, null); 
Iterable<? extends JavaFileObject> fileObjects = fileManager.getFileObjects(sourceFile); 
CompilationTask task = compiler.getTask(null, fileManager, listener, Arrays.asList(options), null, fileObjects); 
task.call(); 

但是,由於類路徑不再包含所需的路徑,所以這不適用於OSGi包。在應用程序的重構OSGi版本中,編譯器需要訪問與上述代碼相同的包中的類以及其他包中的類。我如何讓編譯器知道這些類?

我想到了兩個可能的解決方案:

  1. 給編譯器由包含上面的代碼,因爲它知道一切必要的類的包中使用的類加載器。但是,這看起來並不像我讀過herehere的可行解決方案。
  2. 使用已安裝軟件包的物理位置構建類路徑。我看過org.osgi.framework.Bundle.getLocation(),但我不確定這是否是可靠的解決方案。我得到的路徑(至少在Eclipse中部署時)是相對的,我不確定他們是否可以安全地跨所有平臺和情況使用。

以上選項二看起來可能嗎?有更好的解決方案嗎?

+0

還有一點需要注意:我已經看到了一個方法[here](http://blog.linkedin.com/2008/06/12/osgi-at-linkedin-java-compilation-in-osgi/)工作,但它取決於內部的JDT類。從我讀過的,這不是一個好習慣。 –

+0

任何人有任何想法...? –

回答

3

我在GitHub上創建了一個工作示例。

它不是選項1或2,它會創建一個自定義的JavaFileManager,它會查看所有包並檢索其資源。

事情需要考慮:

  • 它使用JSR 199編譯API,但它僅適用於在OpenJDK/Sun編譯,在Eclipse JDT編譯器似乎在這方面打破。
  • 我只在Equinox上測試過,我沒有使用任何春分特定代碼,所以它應該在其他實現上工作。
  • 它沒有被優化,所以它可能很慢和/或內存很大。
  • 它確實註冊了一個綁定監聽器,因此當它提供某個軟件包的軟件包可以解析或解析軟件包時,它會刷新它的類緩存。我認爲這對於拆分軟件包並不是非常確定的。
  • 它使用BundleWiring API,這是在OSGi的4.3推出,所以它不會工作在OSGi上(Karaf 2.X例如)

我應該提到Technology Excruciation舊的OSGi實現,他的例子幫助我非常驚訝。