在 OSGi 容器中查询功能的正确方法是什么

What is the right way to query for capabilities in the OSGi container

我曾经使用 PackageAdmin.getBundles() 来查询通过 symbolicName 和版本范围安装的包。但是这个 class 已被弃用。

现在我知道我应该使用 IdentityNamespace(在本例中)使用功能和查询包。

但是查询容器中安装的所有捆绑包所提供的功能的正确且最快的方法是什么?

我是否应该自己创建一个方法,从 BundleContext.getBundles() 获取所有包的数组。然后遍历这样的数组,为 BundleRevision 调整每个包,然后尝试匹配其 getDeclaredCapabilities() 方法返回的功能?或者还有其他简单的方法?

Should I create myself a method that gets an array of all bundles from BundleContext.getBundles(). Then traverse such array adapting each bundle for BundleRevision and then trying to match against the capabilities returned by its getDeclaredCapabilities() method ? or there are other simple ways?

差不多。你应该:

  • 从 bundleContext 获取可用的包
  • 使捆绑包适应 BundleWirings
  • 从 BundleWirings 获取功能

例如:

Bundle[] bundles = context.getBundles();
foreach(Bundle : bundles) {
    BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
    List<BundleCapability> capabilities = bundleWiring.getCapabilities(null);
    myCapabilityBasedLogic(capabilities);
}

有关详细信息,请参阅 documentation of BundleWiring class。

更新

如果 Bundle 处于安装状态,则它没有 BundleWiring。我写了一个代码片段来获取之前安装的包的功能:https://github.com/everit-org/osgi-lqmg/blob/master/src/main/java/org/everit/osgi/dev/lqmg/internal/EquinoxHackUtilImpl.java.

查看函数 getAllCapabilities(bundles, state)

相关代码片段:

PlatformAdmin platformAdmin = systemBundleContext.getService(platformServiceSR);
State state = platformAdmin.getState();
Bundle[] bundles = systemBundleContext.getBundles();

List<BundleCapability> availableCapabilities = new ArrayList<BundleCapability>();
for (Bundle bundle : bundles) {
    BundleDescription bundleDescription = state.getBundle(bundle.getBundleId());
    List<BundleCapability> declaredCapabilities = bundleDescription.getDeclaredCapabilities(null);
    availableCapabilities.addAll(declaredCapabilities);
}
return availableCapabilities;

我猜Felix也有类似的可能性。如果您发现它是如何工作的,请与我分享,我也会为 Felix 创建一个 HackUtil 实现 ;)。

如果你想要一个通用的手工解决方案,你可以解析Provide-CapabilityExport-Packageheaders 已安装的 Bundle。您可以用 felix-utils 解析 header。这个库被嵌入到许多技术中,但我也 re-packaged 它并将它作为 OSGi bundle 上传到 maven-central。您的代码可能类似于以下内容:

Dictionary<String, String> headers = installedBundle.getHeaders();
String header = headers.get("Provide-Capability");

if (header != null) {
    // Parse with felix-utils
    Clause[] clauses = Parse.parseHeader(header);
    for(Clause clause : clauses) {
        String nameSpace = clause.getName();
        Attribute[] attributes = clause.getAttributes();
        Directive[] directives = clause.getDirectives();

        processCapability(nameSpace, attributes, directives);
    }
}

您必须根据需要实施 processCapability。您还可以解析 Export-Package header 并将它们转换为基于 OSGi 规范的功能。