1

わかった。したがって、次の方法でプログラムで作成した org.osgi.framework.launch.Framework があります。

framework = ServiceLoader.load(FrameworkFactory.class).iterator().next().newFramework(getFrameworkConfig());
framework.start();
installBundles(BUNDLES_PATH); // installs bundles from a directory, by searching BUNDLES_PATH recursively for JARs

私がやりたいことは、インストールされたバンドルをスキャンし、それらの Export-Package: 宣言を読み取り、クラスの packageName に基づいて正しいバンドルの loadClass メソッドを呼び出すユニバーサル loadClass メソッドを (このクラスのメソッドとして) 持つことです。パラメーターとして渡しています。

これを行うスマートな方法はありますか?または、これを行う方が良いですか:

Class<?> c = null;
// else try every installed bundle one-by-one
for (Bundle bundle : framework.getBundleContext().getBundles()) {
   try {
      c = bundle.loadClass(className);

   } catch (ClassNotFoundException e) {
      // OK, move onto next bundle
      continue;
   }
   if (c != null)
      break;
}
return c;

サービスを使用して、バンドルに利用可能なサービスを公開させ、フレームワークに getAllServiceReferences() を使用してサービスをクエリさせることができますが、これはプログラマーにとってより多くの作業であり、宣言型サービスのルートに行きたいかどうかはわかりません。

4

1 に答える 1

2

私はこのアプローチを取ることに対して警告します。OSGiフレームワークには、パッケージの複数のプロバイダーまたはバージョンを含めることができます。これに正しく対処する統合クラスローダーを作成しようとするのは簡単ではありません。ただし、エクスポートされるパッケージを照会する場合は、使用しているOSGiのバージョンに応じて2つのオプションがあります。

OSGi R4.3より前のOSGiを使用している場合は、PackageAdminを使用できます。これは、サービスレジストリに登録されているサービスであり、フレームワークのバンドルによってエクスポートされるパッケージを照会できます。特に興味深いのは、getExportedPackageメソッドです。これにより、パッケージのプロバイダーを選択してから、パッケージを提供するバンドルでloadClassを呼び出すことができます。

PackageAdminはR4.3で非推奨になりました(ただし、equinoxはまだそれを実装しています)。これはもっと複雑です。希望することを行うには、新しいBundleWiringAPIを利用する必要があります。これには、システム内の各バンドルを取得し、次のことを行う必要があります。

BundleWiring bw = bundle.adapt(BundleWiring.class);
List<BundleCapability> capabilities = bw.getCapabilities(BundleRevision.PACKAGE_NAMESPACE);
for (BundleCapability bc : capabilities) {
    String pkg = bc.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE);
}

この場合、複数のプロバイダーに対応し、正しいプロバイダーを選択する必要があります。正しいものを見つけることは難しい部分です。

于 2011-08-31T01:18:32.473 に答える