2011-06-24 61 views
12

我是OSGi的新手,並創建了一個在Apache Felix OSGi容器中運行的OSGi包。 包中包含文件資源,我需要將其傳遞給方法java.io.File。要實例化File對象,「文件」 - 方案中的URI或字符串路徑是必需的。我如何以乾淨的方式檢索這些內容?如何訪問OSGi包內的文件?

我嘗試使用 context.getBundle().getResource("/myfile")(其中上下文類型爲org.osgi.framework.BundleContext),它返回URI bundle://6.0:0/myfile。 但是由於該URI具有「bundle」方案,因此無法使用File(URI uri)構造函數將其轉換爲File-instance。

可以嘗試構建知道工作目錄並利用bundle的bundleId的路徑,但我懷疑這是最佳實踐。

任何想法?

+0

春分具有特殊的實用工具類,在面向未來的方式做這樣的轉換,但我不知道費利克斯。如果您想要使用乾淨的OSGi API進行編碼,則需要將該文件複製到某處,以便輕鬆檢索相應的File對象(例如,在您的Bundle.getDataFile()存儲中)。 –

回答

12

由於文件是裏面的你的包,你無法使用標準的File去它。您從Bundle.getResource()獲得的URL是獲得這些資源的正確方式,因爲OSGi API也適用於沒有實際文件系統的系統。我會一直試圖堅持使用OSGi API,而不是使用框架特定的解決方案。因此,如果您對該方法有控制權,我會更新它以採用URL,或者甚至可能是InputStream(因爲您可能只是想閱讀它)。爲方便起見,您可以隨時提供確實需要File的幫助方法。

如果你沒有過的方法控制,你將不得不寫一些輔助方法,是以URL,流出來的文件(例如,File.createTempFile()可能會做的伎倆。

+0

感謝您的回答。我無法控制該方法,因爲它是我無法修改的依賴項,並且此依賴項指示File類型的參數。要解釋您的答案:建議通過InputStream訪問文件,並將其作爲臨時文件寫入通過OSGi-API引用的包的專用區域。這是一般的最佳做法嗎?因爲使用這種技術,資源在物理內存中翻倍。假設你有多個文件,它們都會翻倍,這可能是小設備上的一個問題。或者我錯過了一點? – mtsz

+0

你是絕對正確的,這是一種低效率,由OSGi之間的哲學差異(「每個資源都有一個URL,即使我們沒有文件」)和你的庫(「我必須有一個文件」 )。您可以使用臨時文件,也可以使用捆綁存儲;最適合你的情況。 –

+1

安傑洛是正確的...你使用的圖書館設計得很差。它堅持要給它一個文件,但是你所擁有的不是一個文件,而是一個文件的片段(從技術上說,是一個ZIP的輸入)。效率低下是不可避免的。 –

6

也許該API是混淆的,但您可以訪問一個OSGi包這樣的內部文件:

URL url = context.getBundle().getResource("com/my/weager/impl/test.txt"); 

// The url maybe like this: bundle://2.0:2/com/my/weager/impl/test.txt 
// But this url is not a real file path :(, you could't use it as a file. 
// This url should be handled by the specific URLHandlersBundleStreamHandler, 
// you can look up details in BundleRevisionImpl.createURL(int port, String path) 
System.out.println(url.toString()); 

BufferedReader br =new BufferedReader(new InputStreamReader(url.openConnection().getInputStream())); 
while(br.ready()){ 
    System.out.println(br.readLine()); 
} 
br.close(); 

getResource會發現在整個OSGI容器就像OSGI類加載器的理論資源
getEntry會發現RESOUR ce從本地捆綁。並且返回url可以被轉換爲文件,但可以是inputStream。
以下是與此相同的問題:No access to Bundle Resource/File (OSGi) 希望這對你有所幫助。

1

我用的是什麼getClassLoader()的getResourceAsStream():

InputStream inStream = new java.io.BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(fileName)); 

這樣該文件會從你的資源目錄加載。 FileName應包含「src/main/resources」之後的路徑。

完整的示例在這裏:

static public byte[] readFileAsBytes(Class c, String fileName) throws IOException { 
    InputStream inStream = new java.io.BufferedInputStream(c.getClassLoader().getResourceAsStream(fileName)); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int nbytes = 0; 
    byte[] buffer = new byte[100000]; 

    try { 
     while ((nbytes = inStream.read(buffer)) != -1) { 
      out.write(buffer, 0, nbytes); 
     } 
     return out.toByteArray(); 
    } finally { 
     if (inStream != null) { 
      inStream.close(); 
     } 
     if (out != null) { 
      out.close(); 
     } 
    } 
}