2017-10-30 4 views
1

bundleAというアクティブなバンドルがあり、別のバンドルからdoSomething()というメソッドでExampleというクラスを実装しています。 ExampleImplExampleを実装し、ServiceLoaderによってロードされます(SPI Flyのおかげで)。 ExampleImpl.doSomething()bundleAでは、doSomething()を呼び出すバンドルのBundleWiringを取得する必要があります(BundleまたはBundleContextはAPIを変更できないため)。私はbundleAさんBundleWiringはなく、呼び出し元のバンドルのBundleWiringを取得することができます:OSGiでコーリングバンドルのバンドル配線を取得するにはどうすればよいですか?

Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class); 
BundleWiring bundleWiringOfBundleA = bundle.adapt(BundleWiring.class); 

私が呼び出しバンドルのBundleWiringを入手するにはどうすればよいですか?

私の特定のケースでは、発信バンドルは常にLiferay Portal 7.0で実行されているWABになります。ですから、Liferayポータルに固有の解決策があればそれを受け入れますが、より一般的なOSGiソリューションでも問題ありません。

呼び出しバンドルのバンドル配線は、現在のバンドル配線に依存するすべてのバンドルのバンドル配線ではありません。私は現在のバンドルの配線に依存しているバンドル配線を得ることができることを知っているが、それは私が、具体的呼び出しバンドルを得る助けにはなりません。

Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class); 
List<BundleWires> bundleWires = 
    bundleWiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE); 
bundleWires.get(0).getRequirerWiring(); 
+0

なぜBundleWiringが必要ですか? –

+0

@ChristianSchneider、私はWAB(または呼び出しバンドル)の 'BundleWiring'を取得したいので、WABが依存するすべてのバンドルを見つけることができます。私はすべての依存関係を見つけたいので、依存関係にある特定のファイルと注釈付きクラスを見つけることができます。私は技術的にOSGiバンドルであるいくつかのjarファイルで作業していますが、実際にはOSGi環境用にセットアップされていません。だから私は、OSGiフレンドリーになるようにすべてを書き直すことなく動作させることができるかどうかを見極めようとしています。 – stiemannkj1

答えて

0

、呼び出しWABのBundleContext"osgi-bundlecontext"としてServletContextに格納されます。

BundleContext bundleContext = servletContext.getAttribute("osgi-bundlecontext"); 
Bundle bundle = bundleContext.getBundle(); 
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class); 

だから、限り、あなたはLiferayの中ServletContextへのアクセス権を持っているとして、あなたは呼び出しバンドルのBundleBundleWiringを得ることができます。

0

あなたがこれを行うことはできません。 OSGiはクロスバンドルメソッドの呼び出しには全く介入しないので、この情報を取得しようとする可能性があるのは、Thread.currentThread().getStackTrace()でアクセスされるJavaコールスタックだけです。しかし、これが返すオブジェクトStackTraceElementは、java.lang.Classというオブジェクトではないクラス名しか持たないので、それらを戻ってバンドルに関連付ける方法はありません。

これは不可能ではありませんが、これは良いアイデアであると私は非常に懐疑的です。実装クラスをエクスポートしてはならず、呼び出し側を機密扱いにすることはできません。

呼び出し元のバンドルに敏感な動作を実装する必要がある場合は、実現するための標準的で正しい方法は、ServiceFactoryインターフェイスを使用してサービスを登録することです。

+0

おっと、そうです、私は 'ExampleImpl'を輸出していません。私は質問を編集しました。 – stiemannkj1

+0

これで、呼び出し元のバンドルがExampleImplをどのように保持するかは不明です。それはサービスとして登録されていますか? –

+0

ええ、 'ExampleImpl'は' ServiceLoader'を介してSPI Flyでロードされます。 – stiemannkj1

0

BundleTrackerを使用して、インストールされているすべてのWABに反応することができます。次に、各WABをイントロスペクトすることができます。たとえば、アノテーションのスキャンクラスを指定できます。

宣言型サービスと既存のWABサポートは、このように動作します。そのようなエクステンダーを書くことは簡単ではありません。

0

APIを変更することはできません。しかし、呼び出しバンドルを変更できますか?そうであれば、呼び出し元のバンドルが元のバンドルの代わりに使用する「プロキシ」サービスを持つことができます。その後、Bundleおよび/またはBundleContextをプロキシサービスに渡して、そこに依存関係ロジックを置くことができます。

もう1つの選択肢は、ThreadLocalという変数を使用してこの情報を呼び出されたバンドルに渡すことですが、そのアプローチがもたらす副作用についてはわかりません。Liferayので

関連する問題