サービスを利用するためにBundleContextに登録されているサービスの追跡を行うServiceTracker
サービスを利用するためにBundleContextに登録されているサービスの追跡を行うServiceTracker
今度は「jp.co.thinkit.equinox.hello.ui」プロジェクトにある「META-INF/MANIFEST.MF」を開いてください(リスト4)。
リスト4:jp.co.thinkit.equinox.hello.uiのMANIFEST.MF
(省略)
Bundle-Name: Ui Plug-in
Bundle-SymbolicName: jp.co.thinkit.equinox.hello.ui
Bundle-Version: 1.0.0
Bundle-Activator: jp.co.thinkit.equinox.hello.ui.internal.UIActivator
Import-Package: org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.3.3"
Eclipse-LazyStart: true
Require-Bundle: org.eclipse.jface
Export-Package: jp.co.thinkit.equinox.hello.ui
「jp.co.thinkit.equinox.hello.ui」プロジェクトでは「Bundle-Activator」として 「jp.co.thinkit.equinox.hello.ui.internal.UIActivator」クラスを指定しています。
それでは「jp.co.thinkit.equinox.hello.ui.internal.UIActivator」クラスを開いてください(リスト5)。
リスト5:jp.co.thinkit.equinox.hello.ui.internal.UIActivatorクラス
startメソッドにて「org.osgi.framework.ServiceTracker」クラスのインスタンスを作成しています。この ServiceTrackerクラスはその名の通り、OSGiフレームワークに登録されているServiceを追跡するクラスです。
コンストラクタにはBundleContextのインスタンス、サービス名、フィルタを指定します。
インスタンスを作成後、ServiceTracker#open()メソッドを呼び出すことでOSGiフレームワークに登録されているサービスの追跡を開始します。サービスの取得はUIActivatorクラスの43行目で行っています(リスト6)。
リスト6:jp.co.thinkit.equinox.hello.ui.internal.UIActivatorクラスの43行目
Object[] services = tracker.getServices();
このように呼び出すことでServiceTrackerクラスが追跡しているサービスをすべて取得しています。ServiceTrackerの主要なメソッドを表2に示します。
| メソッド名 | 役割 |
|---|---|
| open() | サービスの追跡を開始します。 |
| getService() | 追跡しているサービスの中で一番優先度の高いサービスを返却します。同じ優先度だった場合はIDが小さい方(先に登録された方)を返却します。 |
| getServices() | 追跡しているサービスをすべて取得します。 |
| close() | サービスの追跡を終了します。 |
OSGiではBundleContextインターフェースとServiceRegistrationインターフェース、ServiceTrackerクラスを操作することでサービスの動的な追加を実現しています。
まとめ
今回はBundle同士がどのように組み合わさっているのか、ソースコードを元に解説しました。解説したクラスはほとんどインターフェースばかりで、役割も細分化されています。
| インターフェース名 | 役割 |
|---|---|
| BundleActivator | Bundleの起動・停止時の制御を実装する。MANIFEST.MFに指定することで利用する。 |
| BundleContext | OSGiフレームワーク全体で共有するサービスの制御やBundleの情報を取得する。 |
| ServiceRegistration | Bundleに登録されたサービスを制御する。 |
| ServiceReference | Bundleに登録されたサービスの参照情報やサービスのプロパティを取得する。 |
| ServiceTracker | BundleContextに登録されているサービスを追跡する。 |
DIコンテナが利用されるようになってからインターフェースをベースとしたプログラミングが推奨されるようになりました。モジュラリティが向上していけば、ますますその傾向が強くなるでしょう。
BundleContextを通してOSGiフレームワークへ登録したサービスを、BundleContextに登録したときに用いた名前で取得できる点は、DIコンテナと類似しています。代表的なDIコンテナであるSpringフレームワークでもBean定義を操作することで同様の操作を実現でき ます。
しかし、動的にサービスを追加・削除する操作はOSGiの方が、既存の環境にサービスを容易に追加できることを実感していただけるのではないでしょうか。
次回は最終回ですので、第1回で解説した現状の問題を、「モジュラリティの向上」によってどう解決しているかについて紹介し、連載全体を総括します。
