如何使资源文件对 OSGi 中的所有包可见?

How to make a resource file visible to all bundles in OSGi?

我想在我的包中包含一个资源文件(例如一些 xml 配置文件),并使其对容器中的所有其他包可见。是否可以不使用 Fragment-Host 清单 header?我希望这个资源文件在我的包旁边的所有包 运行 的类路径中始终可见,即使那些还不存在但将来可能会添加的包也是如此。

编辑:

澄清 - 该资源必须被动可用,即其他包应该能够在它们的类路径中找到它,而不是通过引用我的包的任何特殊 API 或服务。

更多背景信息 - 我的环境有点乱,但我无法控制它,也无法更改其现有包。我可以修改它的唯一方法是添加我自己的包。该环境包括 ch.qos.logback.classic bundle 的多个副本。当 logback 启动时,它会在类路径中查找特定的 XML 配置文件。如果它没有找到任何一个,那么它的默认行为是将所有内容打印到调试级别的标准输出。此环境以前用于托管 GUI 应用程序,因此之前并没有那么重要,但现在我正在尝试对其进行调整,以便我可以在无头模式下使用它的一些功能。因此,现在对我来说,能够以仅将警告和错误打印到控制台的方式进行配置变得很重要。

您不能通过这种方式更改其他包的类路径。

您可以做的是从您的 bundleContext 中检索您的包的类加载器。您可以将此类加载器提供给另一个包以检索您的资源。

ClassLoader cl = context.getBundle().adapt(BundleWiring.class).getClassLoader();

另一种选择是将资源的 URL 分配给另一个捆绑包。

只要资源在 class 路径上,任何 bundle 都可以访问该资源,前提是它可以获取包含该资源的 bundle 的 class 加载器。

例如:

ClassLoader classLoaderOfBundleWithResource = ...
classLoaderOfBundleWithResource.getResourceAsStream("org/example/resource.xml");

从维护和 API 的角度来看,我不建议以这种方式公开资源。 Java 类型因此更适合。相反,让资源包导出一个 class,使客户端可以访问资源的内容。

例如:

public class XmlDocumentProvider {
  public InputStream openDocument() {
    return getClass().getResourceAsStream("resource.xml");
  }
}

假设 resource.xmlXmlDocumentProvider 都位于同一个包中,openDocument 将 return 资源内容与第一个示例中一样。

一般来说,不,你不能这样做。 Class-space 隔离是 OSGi 的核心,但您想将资源放入一个包的 class 加载器中,并使其对所有其他包可见。那不是 OSGi,它是全局应用程序 classpath.

要添加到特定包的内部 class 路径,您唯一可以做的就是编写附加到该包的片段。一个片段可以附加到多个主机包,但 如果这些主机具有相同的符号名称,即因为它们是同一包的不同版本。请参阅 OSGi R6 核心规范第 3.14 节。

但是您确实声明了您要附加的捆绑包都是 ch.qos.logback.classic 的副本。如果这意味着它们都有那个确切的符号名称,那么也许一个片段毕竟可以工作。