OSGi:以编程方式决定是不是可以启动捆绑包
Posted
技术标签:
【中文标题】OSGi:以编程方式决定是不是可以启动捆绑包【英文标题】:OSGi: Programatically decide either a bundle can be startedOSGi:以编程方式决定是否可以启动捆绑包 【发布时间】:2015-02-06 13:50:51 【问题描述】:上下文
我有一个基于 OSGi(Equinox 3.9/Eclipse RCP 4.4)的大型应用程序,带有一些“可选”包。这些可选捆绑包中的每一个都提供替代用户界面和一些额外服务(通过 SCR 组件),这些服务仅适用于我们的一部分客户。
应用程序始终作为预打包安装分发(也就是说,我们不使用 P2 或任何其他自动配置机制)。直到最近,我们为每个需要一些可选捆绑包的客户构建了不同的预打包安装。现在可选捆绑包的数量正在增加,要构建的自定义预打包安装的数量也在增加。
因此,我们希望只构建一个安装包以交付给所有客户,其中包含所有可选捆绑包,然后在运行时决定应启动哪些可选捆绑包。但这里有一个转折点:要启用的可选功能集只有在用户通过服务器验证了自己之后才知道。也就是说,一些最终用户可以访问多个帐户,每个帐户都可以访问要启用的一组不同的可选功能。因此,在用户登录之前,可选包必须保持不可用,然后,只应加载允许的可选包。由于这些可选包通过各种扩展程序(Eclipse 的插件注册表、SCR 和蓝图)做出贡献,这意味着在确定它们确实被授权启动之前,不得允许可选包达到 RESOLVED 状态。还必须能够加载和卸载这些可选包,因为用户登录和注销特定的服务器帐户。
可能的解决方案和问题
我已经确定了一些潜在的解决方案,但每个人都有未解决的问题。所以我真的只需要对以下任何一种情况的所有问题都有正确的肯定答案。
拥有可选捆绑包需要一些“启用”功能。我认为这将是最简洁的方法。可选捆绑包会添加类似“Require-capability: com.acme.optionalfeatures; identifier=my-custom-feature-identifier”的内容。在运行时,在用户被认证之前,该功能将保持未解析,因此扩展程序将自动忽略该捆绑包。注册启用功能后,捆绑软件将自动更改状态。那太棒了。但这里有一些缺失的部分:a) 如何注册新的功能命名空间? b) 我可以动态更改捆绑包提供的功能,如果可以,我该怎么做所以? c) (如果 (b) 不可行)我可以动态注册一个具有新功能的新“资源”,如果可以,我该怎么做?
让可选捆绑包导入一些“启用”包。这是上一个场景的变体,它可能比自定义功能命名空间更容易管理......那些“启用包”然后可以通过“动态创建”的包来存在。也就是说,某些管理器捆绑包会调用 BundleContext#installBundle(String, InputStream),并带有一个 ByteArrayInputStream,返回一个动态生成的捆绑包存档,其中包含一个 Manifest.MF,它导出适当的“启用包”。听起来很简单,但是工具链中的几个组件(IDE、PDE、P2、产品导出...)会抱怨这些必需的包不存在。为了避免这些问题,需要在安装到框架时动态添加 require-package 标头。但是是否有任何机制允许尽早更改包的标头(即一旦包安装到框架中)?类编织在这里不适用。
李>所有可选包都需要一个启用包(都一样),这确实存在。 然后,当可选捆绑包尚未获得授权。但是我以后如何在用户登录或注销时请求重新考虑解决所有捆绑包?
排除的解决方案
以下解决方案已被排除:
将可选包放在不同的目录中,然后使用 BundleContext#installBundle(...) 启用这些包。尽管此解决方案在部署时确实有效,但它给开发带来了很大的负担(因为相对于工作区、本地 git 配置、测试环境等而言,捆绑包位于某个难以预测的文件夹中,因此无法正确构建要提供给#installBundle 的位置)。打包过程也变得更加复杂,因为我们首先需要将这些可选包分开,然后更新几个 Equinox/P2 配置文件,以防止它们找到这些现在丢失的包。
通过有条件地从其激活器中抛出异常来防止可选包被激活。这根本无法解决我们的问题,因为仍然允许选项包达到 RESOLVED 状态,因此能够通过扩展器的中间体做出贡献。
使用 P2 在运行时安装新功能。这里的问题是,通过 P2 对捆绑列表所做的更改 1) 本质上是持久的(这意味着可选功能将在下次启动时自动重新启用)并且 2) 需要重新启动框架才能正确完成。
注意:我们对这些额外的捆绑包实际上分发给不需要它们的用户这一事实没有“安全”相关的担忧。我知道用户可能很容易破解安装以强制启动一些可选捆绑包。这不会造成重大问题。
【问题讨论】:
好的,终于了解了有关功能如何工作的更多细节。能力名称空间不得以任何方式在框架中“注册”。除了核心规范中提到的少数命名空间外,任何捆绑清单中引用的所有其他功能都由框架简单地作为“通用功能”添加到功能字典中(这是我的问题 1a)。此外,除了系统捆绑包之外,捆绑包无法动态声明新功能或更改其现有功能之一的值(即问题 1b)。 【参考方案1】:您可以创建和安装一个捆绑包,该捆绑包提供可选捆绑包所需的功能或包。这将使它们得以解决。
但我不明白当多个用户以不同的权限访问服务器时,您的模型将如何工作。更高权限的用户会导致可选包“激活”,因此这些功能将可供同时访问服务器的低权限用户使用。
【讨论】:
抱歉,如果不清楚:捆绑包将加载到客户端基于 Eclipse RCP 的应用程序中,而不是服务器内。 至于提供“启用”包或功能的捆绑包,我需要“按需”创建它... 或者将其预构建为包中的资源,以确定用户是否具有适当的权限。然后,您可以从该捆绑包中的资源安装它。 确实比动态生成它们更容易,但这种情况下的主要困难仍然是工具链(主要是 PDE 和 P2),它会在开发过程中抱怨无法解决的依赖关系,实际上会阻止我构建产品... 这是一个新问题,我认为您可能是最好的人之一...有什么办法(我可以接受这部分的 Equinox-only 解决方案)确定我通过 BundleContext#installBundle(String, InputStream) 安装的包不会被记住并在下一次框架启动时自动重新安装?在正常执行中,我在退出前显式删除了捆绑包,但如果程序意外退出,我将没有机会执行清理...以上是关于OSGi:以编程方式决定是不是可以启动捆绑包的主要内容,如果未能解决你的问题,请参考以下文章
使用不同的启动级别来管理 OSGi 包之间的依赖关系是不是合理?
启动捆绑包时缺少要求 osgi.wiring.package
OSGi 捆绑包未启动:缺少要求 osgi.wiring.package; > &(osgi.wiring.package=org.apache.felix.dm)