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

级别: 初级

马 吉荣 ([email protected]), 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 程序可以完成绝大部分的企业应用需求。


使用RCP组件实现程序在线升级更新_第1张图片

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.

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


使用RCP组件实现程序在线升级更新_第2张图片

最后,键入一个更新站点的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) 页内容大致如下图所示:


使用RCP组件实现程序在线升级更新_第3张图片

切换到配置页,将我们的功能部件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应用:


使用RCP组件实现程序在线升级更新_第4张图片




回页首


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"菜单来对产品进行更新:


使用RCP组件实现程序在线升级更新_第5张图片

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



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


使用RCP组件实现程序在线升级更新_第6张图片

自动更新

为 了使更新过程更加智能,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会自动弹出一个窗口,提示用户是否存在新的版本可用并进行安装。


使用RCP组件实现程序在线升级更新_第7张图片

有一点需要注意: 在更新到新的版本后(其实是下载新版本的插件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.zip 27KB HTTP
关于下载方法的信息


参考资料

  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及数据库等相关领域。联系方式:[email protected].

你可能感兴趣的:(eclipse,manager,application,url,扩展,产品)