使用RCP组件实现程序在线升级更新

级别: 初级

马 吉荣 (majirong@cn.ibm.com), IBM中国软件开发中心DB2 II Team,软件工程师

2006 年 10 月 12 日

RichClient Platform,顾名思义,是一个构建富客户端应用的平台,基于Eclipse的插件体系结构,由一系列所需要的最小插件集合所组成。一般来说,一个 RCP应用程序在发布时有两种类型:基于插件(Plug-in)和基于功能部件(Feature)的。为了使用 Eclipse平台所提供的丰富功能(比如Update,Web Start),我们必须开发基于功能部件的 RCP 应用。两者之间的转换也是非常容易的。这篇文章使用 Eclipse3.2版本作为开发平台,提供了一个小型的 RCP 应用例程,并使用 Update Manager 来实现产品的自动更新。

简介

Eclipse RCP 是 Eclipse Platform 的一个子集(如图),从 Eclipse3.0版本开始,Eclipse项目组对代码进行了重构,将 IDE 与 Workbench(工作台)彻底分离,实现了一个 GenericWorkbench,使得基本的 RCP 应用中不再有 IDE 的影子。构成 RCP的最小插件集合包括Runtime,OSGi,SWT,JFace,Workbench 等一些必须的部件,还有一些是可选部件(比如 Help,Update 等,如下图所示),所有这些插件使得我们的 RCP 程序可以完成绝大部分的企业应用需求。



Update 是 RCP 的一个可选部件,它的主要功能包括:

1) 更新已经安装了的功能部件;

2) 寻找新的功能并进行安装;

3) 对已安装的功能部件进行配置。

这篇文章会围绕 Update 这个可选插件,使用 PDE 来开发一个具有自动更新功能的小型 RCP 应用程序。

建议读者先阅读下面的一些链接,以便对 RCP 有一个清晰的概念:

http://www.eclipse.org/articles/Article-RCP-1/tutorial1.html

http://www.eclipse.org/articles/Article-RCP-2/tutorial2.html

http://www.eclipse.org/articles/Article-RCP-3/tutorial3.html





回页首


开始

首先,我们需要一个插件,用来启动 RCP 应用,这个插件会包含基本的应用扩展点,请参考上面的链接。这里,我们使用 PDE 来创建一个 Eclipse 自带的具有一个视图(View)的例子程序。

启 动 Eclipse,打开菜单File->New->Project, 选中Plug-in Project并且键入工程名,比如com.ibm.csdl.guardian.examples.。在下一页中,填写此插件的基本属性信息,对于问题 "Would you liketo create a rich client application?" 选择Yes. 最后,使用所提供的模板 "RCPapplication with a view" 并接受缺省设置来创建一个RCP的插件工程。



浏览插件配置文件plugin.xml, 我们会发现PDE创建了一个application的扩展,这个扩展将会作为RCP应用的程序入口,并且会被另外一个扩展:Product所使用(见本文产品部分)。


<extension id="application" point="org.eclipse.core.runtime.applications">
<application>
<run class="com.ibm.csdl.guardian.examples.Application"> </run>
</application>
</extension>





回页首


功能部件

为 了使用应用程序的更新功能,我们必须为RCP定义一个或多个功能部件(Feature)。打开菜单File->New->Project, 选中 Feature Project 并且键入工程名称,比如com.ibm.csdl.guardian.examples.feature。在下一页,选中刚才所创建的插件工程: com.ibm.csdl.guardian.examples,作为此功能部件所包含的插件。

对于Eclipse3.2版本,一个可执行的RCP应用至少应包含下面的这些插件(Windows平台):

com.ibm.icu,
org.eclipse.core.commands,
org.eclipse.core.contenttype,
org.eclipse.core.expressions,
org.eclipse.core.jobs,
org.eclipse.core.runtime,
org.eclipse.equinox.common,
org.eclipse.equinox.preferences,
org.eclipse.equinox.registry,
org.eclipse.help,
org.eclipse.jface,
org.eclipse.osgi,
org.eclipse.swt,
org.eclipse.swt.win32.win32.x86,
org.eclipse.ui.forms,
org.eclipse.ui.workbench,
org.eclipse.ui.

并且,为了使用RCP应用程序的更新功能,还需要包含下面的几个插件:
org.eclipse.update.configurator,
org.eclipse.update.core,
org.eclipse.update.ui.

所以,同时选中这些插件来完成功能部件工程的创建。



最后,键入一个更新站点的URL和站点名称,Update Manager会使用这些信息来连接一个或多个更新站点。在这里,URL既可以使用网络地址,也可以使用本地的文件系统地址。下面是功能部件的配置文件feature.xml的典型内容:



<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<url>
<update label="Examples RCP" url="file:/D:/temp/updates"/>
</url>






回页首


包装成产品

RCP应用程序在启动时,需要一个application的扩展点或一个product的扩展点作为入口。同时,为了简化RCP应用程序的打包过程,我们使用一个产品配置文件来对例子程序进行设置。其中product 扩展点是基于application扩展点的。

在PDE 的Package Explorer视图中, 选中刚才所创建的RCP插件工程,打开菜单File->New->Product Configuration,键入一个产品配置文件名称,比如examples.product,并且使用缺省设置来完成产品配置的创建工作。

在 产品配置编辑器(product configurationeditor)中,指定产品名称,比如examples。点击New按钮,使用缺省设置或指定一个产品标识,在RCP启动时会 使用这个ID作为应用程序的入口。特别地,对于产品配置类型,要选择基于功能部件(features),否则无法使用更新功能。概览(Overview) 页内容大致如下图所示:



切换到配置页,将我们的功能部件com.ibm.csdl.guardian.examples.feature 添加到部件列表中。如果必要,可以对其它页的属性信息进行更改,这里我们使用缺省值。最后,在插件配置文件plugin.xml中,添加product扩展:


<extension id="product" point="org.eclipse.core.runtime.products">
<product
application="com.ibm.csdl.guardian.examples.application"
name="Examples"/>
</extension>

现在,我们可以切换到概览页,点击 "Launch the product" 来测试我们的RCP应用:







回页首


Update Manager

这只是一个很简单的RCP应用,我们可以在此基础上添加透视图及视图以实现各种各样的功能,但这些不是本文的重点,请参考其它资料。这里,我们将在此应用的基础上添加软件更新功能。

添加更新菜单

首先,应该有一种方式,用来呼叫出更新管理器,我们使用菜单来实现这个功能。在类 ApplicationActionBarAdvisor中,修改 makeActions 方法,,添加一个Update Action:



exitAction = ActionFactory.QUIT.create(window);
register(exitAction);

updateAction = createUpdateAction(window);
register(updateAction);



修改 fillMenuBar 方法,将Update菜单添加到Help主菜单下:

… MenuManager helpMenu = new MenuManager("&Help",IWorkbenchActionConstants.M_HELP); menuBar.add(helpMenu); helpMenu.add(updateAction); …

实现软件更新功能

在类 UpdateAction 中,实现 run 方法如下:


BusyIndicator.showWhile(window.getShell().getDisplay(), new Runnable() {
public void run() {
UpdateJob job = new UpdateJob("Search for update", false, false);//$NON-NLS-1$
UpdateManagerUI.openInstaller(window.getShell(), job);
PlatformUI.getWorkbench().getProgressService().showInDialog(window.getShell(), job);
}
});

记得将 ore.eclipse.update.ui 这个插件添加到com.ibm.csdl.guardian.examples 插件的所需插件列表中,否则上面的类将不能通过编译。

好 了,我们的RCP应用已经具备了软件更新功能!是不是感觉很简单?是的,Eclipse平台一个优美的地方就是将很多功能部件都设计成为一个 Framework,具有很高的可重用性,用户只需做很少量的工作就能实现很复杂的功能,Eclipse的UpdateManager就是一个很好的例 子。再次启动我们的RCP应用,已经可以使用软件更新功能了,如下图。不过,因为更新站点并没有准备好,所以不会发现新的版本,下面会详细介绍这方面的内 容。



打包RCP应用

到 目前为止,这个例子程序一直是作为一个Eclipse的运行时应用来运行的,我们需要将其打包到Eclipse之外,形成一个单独的可执行的应用程序。得 益于Eclipse的插件体系结构,打包的过程将非常简单。当然,我们可以自己编写脚本代码去完成这个步骤,但是在PDE中,提供了一个导出工具,使得我 们可以更加方便的实现这个过程。首先确认插件工程下的build.properties文件包含了所有必需的资源文件,因为PDE的导出向导将会使用 Ant并读取这个配置文件来对每个插件进行打包工作。

现在使用产品配置编辑器打开 examples.product文件,切换到概览页,点击 "Eclipse Product exportwizard" ,弹出导出向导配置窗口。使用 examples.product作为配置文件并键入应用程序的主目录,比如ExampleRCP,PDE在打包时将会创建这个应用程序的根目录。另外, 建议将"Synchronizebefore exporting"选中,以便在打包时检查配置文件是否与所包含的插件相匹配。最后,指定存放此RCP应用的目的文件夹并开始导出过程:



现在,我们可以进入刚才所指定的目的文件夹,通过双击可执行文件(在Launcher页进行配置)来启动应用程序。

准备新版本

假设一下产品已经发布出去,但是客户却想在树上显示四个节点,我们使用Update Manager来实现这个新的需求。

首先,需要在类View 中更改源代码:



public Object[] getElements(Object parent) {
// add the fourth node to satisfy the customer's new requirement.
return new String[] { "One", "Two", "Three", "Four" };
}


下一步需要创建一个更新站点的工程。打开菜单 File->New->Project,选择 Update Site Project,并且为此工程指定一个名称,比如com.ibm.csdl.guardian.examples.site.

在站点清单编辑器中,切换到Site Map页面,将不同的功能部件切分为类别。在Archives页面,设定更新站点的URL及描述信息,URL可以使用本地文件系统,或其它网络协议,比如HTTP等。为了方便测试,这里我们使用本地文件系统目录作为更新站点。



文件site.xml 最终的样子:


<site>
<description url="file:///D:/temp/updates">
Examples RCP Application Update Site
</description>
<feature url="features/com.ibm.csdl.guardian.examples.feature_1.0.0.jar"
id="com.ibm.csdl.guardian.examples.feature" version="1.0.0">
<category name="examples"/>
</feature>
<category-def name="examples" label="examples"/>
</site>

在新版本编译通过之后,修改RCP应用包含的所有插件及功能部件的版本号,确保比发布给客户的版本要高(不要修改插件的ID),以表示有更新版本可用。

在插件com.ibm.csdl.guardian.examples 的MANIFEST.MF文件中:



Bundle-Version: 1.0.1


在feature.xml文件中:


<feature 
id="com.ibm.csdl.guardian.examples.feature"
label="Examples Feature"
version="1.0.1"


因为我们在功能部件的配置中使用了缺省设置 "Synchronize versions on build" ,所以PDE的打包工具会自动为所生成的二进制Jar文件生成正确的文件名以显示新的版本号。

现在的site.xml 文件内容:


<site>
<description url="file:///D:/temp/updates">
Examples RCP Application Update Site
</description>
<feature url="features/com.ibm.csdl.guardian.examples.feature_1.0.1.jar"
id="com.ibm.csdl.guardian.examples.feature" version="1.0.1">
<category name="examples"/>
</feature>
<category-def name="examples" label="examples"/>
</site>

在 站点清单编辑器的Site Map页面中,选中所要更新的功能部件并且点击 "Build",PDE会在此站点工程目录下生成所需要的更新功能部件及插件。将文件site.xml,目录features 和plugins拷贝到feature.xml中所指定的URL(在这里是本地文件系统), 再次启动我们的例子RCP应用,现在即可以使用"Find andInstall"菜单来对产品进行更新:



点击Next,会出现许可证描述信息(在feature.xml指定),只有选择接受许可证之后,下载更新包及安装过程才会继续:



下载并安装完毕之后,会提示重新启动RCP应用,这时即可以看到软件更新之后的效果:



自动更新

为 了使更新过程更加智能,UpdateManager还支持软件的自动更新,并提供了很多选项来对更新时间进行设置。我们所需要做的很简单,只需要将插件 org.eclipse.update.scheduler 添加到 feature.xml的插件包含列表中并添加一个菜单来呼叫出自动更新的配置项页面:



preferencesAction = ActionFactory.PREFERENCES.create(window);
register(preferencesAction);

MenuManager windowMenu
= new MenuManager ("&Window", IWorkbenchActionConstants.M_WINDOW);
menuBar.add(windowMenu);
windowMenu.add(preferencesAction);


从这里可以看出,Update Manager 使用org.eclipse.ui.preferencePages 这个扩展来对更新选项进行配置:



配置完成后,当更新条件满足时,RCP会自动弹出一个窗口,提示用户是否存在新的版本可用并进行安装。



有一点需要注意: 在更新到新的版本后(其实是下载新版本的插件Jar包),老版本的Jar 文件不会被自动删除,因为有时更新会出现问题,用户还可以再使用老的版本。对于这个问题,请参考下面这个链接来得到更多信息: https://bugs.eclipse.org/bugs/show_bug.cgi?id=70990.

管理所安装的功能部件

一 个大型的企业级RCP应用通常会包含大量的功能部件,如果有的功能部件暂时不会被使用,刚可以将其置为不可用状态,这样既可以加速应用程序的启动过程,也 会对RCP应用的性能有所提高。Update Manager也提供了这个功能,我们的例子程序使用一个菜单来呼叫出管理窗口:



manageAction = createManageAction(window);
register(manageAction);

MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP);
helpMenu.add(manageAction);


在类 ManageAction 中,实现 run 方法如下:


BusyIndicator.showWhile(window.getShell().getDisplay(), new Runnable() {
public void run() {
UpdateManagerUI.openConfigurationManager(window.getShell());
}
});

当点击此菜单后,即会弹出产品配置窗口,可以方便的管理所安装的功能部件:







回页首


结论

使 用UpdateManager不仅可以方便的给RCP应用程序添加软件更新功能,还可以对所安装的功能部件进行方便的管理。得益于 UpdateManager的框架结构(其它Eclipse的组件也是如此),我们还可以利用其所提供的API,对产品的更新功能进行定制,使得产品具有 自己的特色。






回页首


下载

名字大小下载方法
updatemanager.zip27KBHTTP
关于下载方法的信息


参考资料

  1. 更多 Eclipse 内容请参考 Eclipse 专题
  2. Eclipse.org Articles. Eclipse.org.
  3. Eclipse Online Help. Eclipse.org.
  4. Eclipse Rich Client Platform-Designing, Coding, and Packaging Java Applications. Jeff McAffer, Jean-Michel Lemieux.


关于作者


马吉荣,IBM中国软件开发中心DB2 II Team,软件工程师,现主要从事GUI Test Automation的框架研究及开发,DB2相关产品的测试工作。研究兴趣包括Eclipse,MDA,XML及数据库等相关领域。联系方式:majirong@cn.ibm.com.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rains卍Soft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值