在之前的一篇blog中我曾经写到过CM对于application level的configuration的不适应,提到的主要是两点:
1、无法在外部统一的对Bundle中service所需要的属性进行管理;
当时基于这个约束,只好在各自的bundle下编写一个管理当前bundle属性的服务,当外部需要管理此bundle的属性时,必须通过这个服务来管理,否则的话改变是不会起到效果的。
2、无法共享属性的配置。
每个bundle都保存自己独立的一份属性配置,这就导致了当出现共享属性时,在管理端也不得不同时去重复的更新多个bundle。
昨天在调试产品的时候,又被CM搞的郁闷了一把,由于CM是根据BundleLocation和service.PID共同来绑定属性的,也就是说当BundleLocation改变了的情况下属性就无效了,而且也无法被重写,这对于实际的应用而言几乎是不可接受的,因为模块部署的路径、模块的名称改变这都是很正常的事,但根据CM这样的方式的话,也就意味着模块部署的路径、模块的名称都是不可改变的。
想想挺恼人的,就开始仔细的看Equinox的CM实现的代码,经过仔细的查看后,发现自己疏忽了一点,冤枉了CM,其实CM也是留了一个口以供上面这样的情况下的处理的,后来对照了下OSGi R4中CM规范的描述,确实如此,如果希望配置不要和bundleLocation绑定,那么可以在注册ManagedService接口实现的服务时将其server.bundleLocation设置为null,如下:
<component name="PortComponent">
<implementation class="com.terdon.spike.port.PortService"/>
<property name="service.pid" value="com.terdon.port"/>
<property name="service.bundleLocation" value="null"/>
<service>
<provide interface="org.osgi.service.cm.ManagedService"/>
</service>
</component> 然后就可以在其他的管理属性的服务中调用ConfigurationAdmin来实现对这个service的属性的管理:
Configuration configuration=admin.getConfiguration("com.terdon.port", null);
根据这样的分析,也就是说我以前所说的第一点的情况是冤枉了CM,现在开始给它平反,:)
摘一下OSGi R4 CM规范中对于这种情况的描述:
"Bundles with the required permission can create Configuration objects that
are not bound. In other words, they have their location set to null. This can
be useful for pre-configuring bundles before they are installed without having
to know their actual locations.
In this scenario, the Configuration object must become bound to the first
bundle that registers a Managed Service (or Managed Service Factory) with
the right PID.
A bundle could still possibly obtain another bundle’s configuration by registering
a Managed Service with the right PID before the victim bundle does
so. This situation can be regarded as a denial-of-service attack, because the
victim bundle would never receive its configuration information. Such an
attack can be avoided by always binding Configuration objects to the right
locations. It can also be detected by the Configuration Admin service when
the victim bundle registers the correct PID and two equal PIDs are then registered.
This violation of this specification should be logged."
从上面这段描述中,可以看出,CM之所以这么设计主要还是从安全性的角度考虑的。
但对于第二点,目前看来确实是如此,属性无法共享,因为pid必须是唯一的,我已经发了邮件给equinox maillist,看看是不是有人会有办法,:)