为基于 Eclipse3.4 的 RCP 应用创建补丁程序
2010-05-18 00:00:00 来源:WEB开发网如果用户在使用过程中发现了产品中的问题,对于研发人员来说,一种解决方案是在下一个发布版本中包含对这些问题的修改。但是如果问题非常紧急,甚至影响了客户的正常工作,通常的做法是创建临时的补丁程序,然后安装到用户的生产环境中。对于基于 Eclipse 的 RCP 产品而言,产品的升级就是插件功能的改进即插件版本的提高。在创建了新版本的插件后,如何交付给用户呢?一种方法是用户通过 Software Update 界面指定 Update Site 进行安装。但是这种机制对于商业化的产品或者对于产品小的改动而言较为笨重,同时由于产品环境是由安装软件定制的,通过 Software update 界面可能无法完成安装。本文介绍了一种通用的方法,创建并部署 Feature Patch,能够比较灵活的解决问题。
Feature 及 Feature Patch 的概念
Plug- in(插件,OSGI 中的 bundle)包含了产品功能的具体实现,但从整个产品的角度看粒度较小,不利于管理。Feature( 功能部件 ) 能将功能相近的插件组织起来,用户管理的是一个个的功能模块,而不需要具体的实现细节,使整个产品的结构层次化。通过使用 Feature 来打包插件,可以做到:
1. 列出所有的前提条件,方便 Eclipse 的配置管理
2. 使用 Eclipse Software update 来对插件进行管理
3. 支持品牌化管理,可以在 feature 中定义一个欢迎页面,让用户对插件的功能更加熟悉。
尽管简单的拷贝 Plug-in 到 eclipse 的 Plugins 目录也能生效,但是这些插件是不被管理的,这种做法是不推荐的。同时如果基于 Eclipse 的 RCP 配置为基于 Feature 进行安装、升级,那么只是生成并拷贝高版本的插件,并不能生效,对于这种场景,就需要以 Feature 为单位来创建补丁程序即 Feature Patch。
Feature Patch 是 Eclipse 支持的一种工程类型,与 Feature 工程结构类似,并不实际参与 Eclipse 启动过程,在 Feature Patch 中会指定对哪个 Feature 创建补丁,特点包括
一般比较小,且必须指定对哪个 Feature 创建补丁
Feature Patch 只包含需要更新的插件,部署后只会对已存在 Feature 中的部分插件进行更新
为简化补丁机制,本文采取增量式补丁,即每个 feature 只包含一个 feature patch 程序。举例来说,假设 Feature A 已经包含了补丁程序 B,那么下次发布的补丁程序应该包含了补丁程序 B 中的修改。
Eclipse 插件的版本规范
在创建 Feature patch 过程中,会更改插件的版本,这就需要读者了解插件的版本规范。在 Eclipse/plugins 目录下的插件名字大都为 org.eclipse.equinox.p2.engine_1.0.4.v20080930.jar 类似结构,其中 org.eclipse.equinox.p2.engine 为此插件的 ID,而下划线后面的为此插件的版本号。在 Eclipse 中,插件的版本号由四部分组成:major.minor.service.qualifer
表 1. Eclipse 插件版本规范
部分名 | 什么时候改变 |
major | 当产品的 API 发生大的变化时,major 部分应该增加,当 major 部分变化时,minor 和 service 部分应该置 0 |
minor | “外部能够看到”的改变,比如说重要的性能改进,主要代码重写 |
service | 不同发布版本之间的插件发生改变,比如代码中的 bug fix,编译选项设置改变 |
qualifier | 不同 Build 之间的变化 |
当 Eclipse 检测到有多个版本的,会根据下列规则决定去加载哪个插件:
加载 major 部分数字最大的插件
若 major 部分相等,则加载 minor 部分数字最大的插件
若 minor 也相同,则加载 service 部分数字最大的插件
若 service 相同,则加载 qualifier 部分 ASCII 码最大的插件
由于 Feature 包含了一些插件,所以 Feature 的版本变化应反映了它所包含的插件与 Feature 中最典型的变化,即:如果任何它所包含的插件与 Feature 版本的 major/minor/service/qualifer 发生变化,需要增加这个 Feature 相应的字段。
在 feature.xml 中定义依赖性时有一个重要的属性 match rule,它定义了 Eclipse 使用的版本过滤算法(只有当 match rule 得到满足时才能进行 Install 或 Update 功能部件操作),Match rule 主要有以下几个可选值:
表 2. match rule 取值范围及说明
Rule | 功能说明 |
perfect | 必须和执行的版本号完全一样 |
equivalent | major 和 minor 部分相同,service 部分需大于或等于指定的版本号 |
compatible | major 部分相同,minor 或 service 部分需大于或等于指定的版本号 |
greaterOrEqual | major 或 minor 或 service 部分需大于或等于指定的版本号 |
创建 Feature Patch
本章节将会介绍怎样通过 Eclipse 提供的 Feature Path 向导来创建 feature patch。在此之前,需要首先创建示例所需要的 feature.
使用“Plug-in with view”创建一个新的 Plug-in 工程“cn.myplugin”,版本为 1.0.0_v20091225
创建新 Feature 工程“cn.myfeature”,版本为 1.0.0,添加上面创建的插件到此 feature
然后可以将“cn.myfeature“工程导出为“Deployable features“,拷贝生成文件到 eclipse 相应目录下来验证 Feature 是否创建成功。
步骤 1:收集与 Patch 相关的信息
在创建 Patch 前,需要明确以下信息:
哪些插件需要更新(本例中为 cn.myplugin)
这些插件属于哪些 feature,及这个 feature 的版本号 ( 本例中为 cn.myfeature_1.0.0)
是不是已经对这个 Feature 创建过 Patch
是否有插件需要在安装的时候进行解压缩
步骤 2:更新插件的版本信息
根据需求,更改完插件代码后,下一步需要通过更改插件版本号将插件标识为新版本的插件。对于一些临时的或比较小的补丁程序时,修改插件版本号中的 qualifier 部分就可以了。对于一个比较大的 fix pack 版本才会去更新版本号的 service 部分。此例中,将 cn.myplugin 的版本改为 1.0.0.v20100101
步骤 3:利用“Feature Patch”向导创建 Feature Patch
通过 File -> New -> Others -> Plug-in Development,创建“Feature Patch”工程,
图 1. Feature Patch 向导
填写跟 Feature Patch 属性信息。Project Name 和 Patch ID 基于被应用 Patch 的 Feature,一般以 feature ID 加 .patch 作为 Project Name。需要注意的是在最后一部分“Properties of features being patched”,一定要选择带有具体版本号的 feature。如果这个被应用 Patch 的 Feature 在 Target Platform 上,可以通过“Browse”进行选择。
图 2. Feature patch 属性对话框
更新 Feature Patch 的版本号,选择所包含的插件,保存所有修改。
图 3. Feature Patch 的 feature.xml 编辑窗口
在创建完 Feature patch 工程后,可以将根据要应用补丁的 Feature 的版本号来更新 Feature Patch 的版本号,然后在图 3 中的 Plug-ins 标签页中添加要更新的插件。默认情况下,插件的版本号是 0.0.0,你可以通过选中“Versions“对话框中的第二项,来显示具体的版本号。
步骤 4:导出 Feature Patch
右击 Feature Patch 工程,选择“Export->Plug-in Development->Deployable feature”,输入要保存的位置,如果 Feature patch、feature 或插件中含有 .qualifier 字段,可以通过切换到 Option 标签页,勾选“Qualifier replacement“进行替换,如下图所示,注意替换字符串对应的 ASCII 码值应比原有插件版本的 qualifier 部分大。点击“Finish”,Feature Patch 就被保存在本地磁盘上了。
图 4. 导出 Feature Patch 工程对话框
对于基于 Eclipse v3.4.0 的产品来说,还需要为 Patch 产生 P2 元数据。而对于 Eclipse v3.4.1 及以后的版本,由于 P2 的变化,则不需要此步。打开命令提示符,切换到 Eclipse v3.4.0 安装目录,运行下面命令即可得到 P2 元数据。
清单 1. 产生 P2 元数据的命令
eclipsec.exe -application org.eclipse.equinox.p2.metadata.generator.EclipseGenerator
-metadataRepositoryName [PATCH NAME] -metadataRepository file:[PATCH LOCATION]
-artifactRepository file:[PATCH LOCATION] -source [PATCH LOCATION]
-flavor tooling -append -noDefaultIUs -inplace -nosplash
部署与验证
将生成的 features/plugins 目录拷贝到产品环境 Eclipse 所在的目录,重新启动应用程序,即完成了 Feature patch 的一次部署。但对于累积式补丁,考虑到用户可能已经安装过旧版本补丁程序,部署流程应能检测到旧版本的补丁程序并移除。借助于 Eclipse Link 机制,将补丁程序安装在 link 文件指向的目录,能够比较安全的实现新版本补丁程序的安装。在具体实施中,可以通过脚本实现文件的拷贝操作,并调用 Eclipse 运行时参数清空 Eclipse 缓存,来确保 Eclipse 加载补丁程序中高版本的插件。
补丁是否被正确的安装可以通过下面三种方法来检验:
通过“Help” -> “About Product Name” ->“Plug-in Details”查看插件的版本号
通过“Help” -> “Software update”查看 Patch 的版本信息
验证为插件新增加的功能是否存在。
新版本插件未生效问题诊断
通过上面的步骤,我们已经能够正确的创建 Feature Patch 并且部署到产品环境。但是当用户使用产品时,产品功能及 Pug-in details 时 plug-in 版本并没有更新,那么常见的原因为:
插件依赖性未满足
插件被多个 feature 包含
本文提供了一种定位原因的思路,首先我们需要了解 Eclipse 启动机制:Eclipse v3.4 基于 Equinox 框架构建,Equinox 完全按照 OSGI r4 规范编写,同时增加了一些自己的扩展,那么在 Eclipse 启动的过程中,主要完成了以下动作,
处理命令行参数
启动 OSGI 框架,安装 bundle
对已经安装的 bundle,检查其依赖是否满足,若满足则置为 resolved
对已经 resolved 的 bundle,调用其 activator 的 start 方法,将 bundle 的状态置为 active 或 lazy-starting
可以通过– console 参数启动 OSGI console 来查看 plug-in(bundle) 的状态,下图为 OSGI 中的 bundle 状态转换图。若插件版本出现在结果中,且 bundle 状态为 installed, 那么说明插件的依赖性未能满足 (match rule 是否与插件的新版本号一致 )。若新版本的插件不会出现在结果中,则可能是插件被多个 feature 包含,这时就需要。
图 5. Bundle 状态图
赞助商链接