2011-06-24 2 views
12

私はOSGiを初めて使用し、Apache Felix OSGiコンテナで実行するOSGiバンドルを作成しました。 バンドルにファイルリソースが含まれていますが、これはメソッドにjava.io.Fileとして渡す必要があります。 Fileオブジェクトをインスタンス化するには、 "file"スキームのURIか、文字列としてのパスが必要です。クリーンな方法でそれらのファイルを取り出すにはどうすればよいですか?OSGiバンドル内のファイルにアクセスするにはどうすればよいですか?

context.getBundle().getResource("/myfile")(コンテキストはタイプorg.osgi.framework.BundleContext)は、bundle://6.0:0/myfileというURIを返します。 しかし、このURIは "bundle"スキームを持っているので、File(URI uri)コンストラクタを使用してFileインスタンスに変換することはできません。

一つは、作業ディレクトリを知り、私のバンドルのbundleIdを悪用した場所へのパスを構築しようとすることができますが、私はこれがベストプラクティスです疑います。

アイデア?

+0

春分は、将来性の方法で、このような変換を行うための特別なユーティリティクラスを持っていますが、私はフェリックスのことは知りません。クリーンなOSGi APIをコーディングする場合は、このファイルをどこかにコピーして、対応するFileオブジェクト(Bundle.getDataFile()ストレージなど)を簡単に取得する必要があります。 –

答えて

12

の中にバンドルがあるので、標準Fileを使用してそのファイルにアクセスする方法はありません。 Bundle.getResource()から入手したURLは、OSGi APIが実際のファイルシステムのないシステムでも動作するようになっているため、これらのリソースを取得する正しい方法です。私は、フレームワーク固有のソリューションを使用するのではなく、常にOSGi APIに固執しようとします。

メソッドを制御できる場合は、URL、またはInputStream(おそらく読んでいるだけなので)の値になるように更新します。便宜上、いつでもになるというヘルパーメソッドをFileと指定することができます。

あなたが方法を制御していない場合は、File.createTempFile()は、おそらくトリックを行います、例えば(ファイルにそれをストリーム、URLを取り、いくつかのヘルパーメソッドを記述する必要があります。

+0

あなたの答えをありがとう。私はこのメソッドを制御できません。それは私が変更できない依存性であり、この依存性はFile型の引数を指定しているからです。あなたの答えを言い換えると、InputStream経由でファイルにアクセスし、OSGi-API経由で参照されるバンドルのプライベート領域に一時ファイルとして書き出すことを提案します。これは一般的にベストプラクティスですか?この手法では、リソースは物理メモリで倍増するためです。複数のファイルがあると仮定すると、すべてが2倍になります。これは小さなデバイスで問題になることがあります。または私はポイントを欠いていますか? – mtsz

+0

OSGi(「すべてのリソースにはファイルがない場合でもURLがあります」)とライブラリ(「ファイルが必要です」)の間の哲学の違いによってもたらされる非効率です。 )。一時ファイルを使用することも、バンドルストレージを使用することもできます。あなたの状況に最も適したものを選んでください。 –

+1

Angeloは正しいです...あなたが使用しているライブラリがひどく設計されています。それはあなたがファイルを与えることを主張しますが、あなたが持っているものはファイルではなく、ファイルの断片です(技術的には、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があります。ローカルバンドルから。 return urlはfileではなく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(); 
     } 
    } 
}