如何编写 Eclipse 安装程序

上次修改时间:2002 年 5 月 6 日,星期一,11:15

需要将基于 Eclipse 的产品正确安装在最终用户的计算机上。特殊用途的封装工具(例如,InstallShieldRPM)通常用来构建自动执行安装、更新和卸载的可执行安装程序。此注释描述如何为基于 Eclipse 的产品以及基于 Eclipse 的产品的可单独安装的扩展编写安装程序。

我们假定产品开发小组应负责提供访问作为可执行安装程序封装的最终用户计算机所需要的大部分内容。可执行安装程序的创建过程被编制成了脚本,原因是安装时操作需要与最终用户交互作用,并将文件保存在用户的计算机上。此注释详细描述了这些安装程序需要执行的操作以及它们应该如何工作。

应该将此注释看作是负责编写基于 Eclipse 的产品的安装程序的人员可使用的好方法。之所以建议所有安装程序的作者都遵循我们的方法,是主要有两个原因:

产品安装程序创建脚本

产品安装程序应该是自包含的 — 可以分布在 CD 上和安装在具有适当操作系统的任何机器上的对象的类型。

Eclipse 需要 Java2“Java 运行时环境”(JRE)来运行 Java 代码。JRE 是从 Java 供应商处获取的许可软件。借助 JRE 供应商提供的重新分发 JRE 的许可证,一个公司可以将 JRE 与它的产品包括在一起,并将它和产品同时安装在最终用户的计算机上。一种替代方法是要求将 JRE 预安装到最终用户的计算机上,并在安装产品时使它与产品相关联。无论如何,基于 Eclipse 的产品都需要适当的 JRE,并且产品安装程序必须在安装 JRE 或者定位和链接至预先存在的 JRE 过程中发挥作用。

假定要将 JRE 与产品一起安装。包含 JRE 的目录是安装程序创建脚本的一个输入。表示此目录 <JRE>。此目录必须具有标准的 JRE 目录结构,并且 Java 可执行文件位于 jre/bin/java.exe,而类库位于 <JRE> 目录下面的 jre/lib/rt.jar。作为参考,此目录的框架结构为如下所示:

<JRE>/
  jre/
    bin/
      java.exe
    lib/
      rt.jar

这些目录中有附加文件(和子目录);我们只显示了一个样本来提供总体结构。用斜体表示的斜体名称是特定于产品的。

安装程序创建脚本的第二个输入是目录(<product head>),该目录包含特定于产品的可执行启动器以及与 Eclipse 不相关的任何文件。作为参考,此目录的框架结构为如下所示(斜体指示将随产品不同而有所不同的文件名):

<product head>/
  acmeproduct.exe

安装程序创建脚本的第三个输入是一个目录(<product body>),该目录包含为产品开发的功能部件和插件。作为参考,此目录的框架结构为如下所示:

<product body>/
  eclipse/
    features/
      com.example.acme.acmefeature_1.0.0/
       feature.xml
      com.example.acme.otherfeature_1.0.0/
        feature.xml
    plugins/
       com.example.acme.acmefeature_1.0.0/
        plugin.xml
        about.ini
        about.properties
        about.mappings
        plugin_customization.ini
        splash.bmp
       com.example.acme.otherfeature_1.0.0/
        plugin.xml
        about.ini
        about.properties
        about.mappings
       com.example.acme.myplugin_1.0.0/
        plugin.xml
        myplugin.jar
       com.example.acme.otherplugin_1.0.0/
        plugin.xml
        otherplugin.jar

安装程序创建脚本的第四个输入是一个目录(<platform>),该目录包含 Eclipse 平台本身的功能部件和插件以及所包括的任何第三方工具。此目录还包括标准 Eclipse 可执行启动器 eclipse.exe(在 Unix 操作环境上,名为 eclipse)、它的同伴 startup.jar 以及必需位于安装的根目录中的其它任何 Eclipse 平台文件。作为参考,此目录的框架结构为如下所示:

<platform>
  eclipse/
    eclipse.exe
    startup.jar
    features/
      org.eclipse.platform_2.0.0/
      org.eclipse.platform.win32_2.0.0/
      org.eclipse.jdt_2.0.0/
      org.eclipse.pde_2.0.0/
    plugins/
      org.eclipse.platform_2.0.0/
      org.eclipse.core.runtime_2.0.0/
      org.eclipse.core.boot_2.0.0/
      org.eclipse.core.resources_2.0.0/
      org.eclipse.ui_2.0.0/
      org.eclipse.jdt_2.0.0/
      org.eclipse.jdt.core_2.0.0/
      org.eclipse.jdt.ui_2.0.0/
      org.eclipse.pde_2.0.0/
      org.eclipse.pde.core_2.0.0/
      org.eclipse.pde.ui_2.0.0/
      (more org.eclipse.* plug-in directories)

<JRE>、<product head>、<product body> 和 <platform> 输入目录的精确内容确定哪些文件最终将安装在最终用户的计算机上。

安装程序创建脚本的最终输入是产品的主要功能部件的标识和版本字符串(例如,“com.example.acme.acmefeature”和“1.0.0”);以及产品可执行文件的名称(例如,“acmeproduct.exe”)。对于不需要它们自己的产品可执行文件的产品,这将是标准 Eclipse 可执行启动器的路径(“eclipse/eclipse.exe”)。这些字符串对于安装程序具有特殊意义,它们出现在文件名和目录名以及在安装时创建的标记文件的内容中。

在安装时,安装程序将以标准方式运行(在步骤的列表后面提供了进一步的详细信息):

  1. 警告用户退出所有程序
  2. 介绍要安装的产品
  3. 如果适当的话,将要求用户提供已注册的所有者的姓名以及许可证密钥
  4. 显示产品的许可证协议,并请求用户接受
  5. 建议磁盘上的某个位置来安装产品(但是允许用户覆盖此缺省值)
  6. 检查产品或扩展是否尚未存储在指定的位置
  7. 要求用户确认有关安装的所有详细信息
  8. 创建标记文件以标记产品安装的根
  9. 将文件复制到磁盘(参见下面的内容)
  10. 如果可能的话,将已注册的所有者的姓名和许可证密钥插入到“关于”描述中
  11. 创建桌面快捷方式来运行产品可执行文件
  12. 创建适当的条目以允许用户卸载产品
  13. 使用 -initialize 选项启动产品可执行文件,以执行所有首次处理
  14. 企图显示产品发行说明(“readme”文件)

如果在步骤 5 中指定的位置是 <install>,则安装程序将把 <JRE>、<platform>、 <product> 和 <product plug-ins> 目录中的所有文件复制到 <install> 中。

输入文件 已安装的文件
<JRE>/* <install>/eclipse/*
<product head>/* <install>/*
<product body>/* <install>/*
<platform>/* <install>/*

在步骤 8 中创建的标记文件是 <install>/eclipse/.eclipseproduct,用来标记已经将基于 Eclipse 的产品安装到的目录,主要是针对要定位的扩展安装程序。此标记文件是一个 java.io.Properties 格式文件(带有“\”转义的 ISO 8859-1 字符编码),并且包含对用户标识产品以及将基于 Eclipse 的一个产品与另一个产品区分开来的以下信息:

name=Acme Visual Tools Pro
id=com.example.acme.acmefeature
version=1.0.0

“id”和“version”属性的值是安装程序创建脚本的输入;产品的名称大致可以推测出来并且准确性较高。(产品通常不会访问此标记文件;只有产品和扩展安装程序才会编写或读取它。)

步骤 6 需要检查现有 <install>/eclipse/.eclipseproduct<install>/eclipse/.eclipseextension 文件。不能将一个产品与另一个产品或扩展安装在完全相同的位置。

在安装所有文件之后,安装目录的顶层结构将包含下列文件和子目录(也许还包含其它内容):

<install>/
  acmeproduct.exe
  eclipse/
    .eclipseproduct
    eclipse.exe
    startup.jar
    features/
    plugins/
    jre/

如果产品安装程序要求用户输入许可证信息(例如,已注册的所有者的姓名和许可证密钥),则此信息应该使它成为产品“关于”对话框(步骤 10)。

这是通过将用户响应记录在主要功能部件的插件的“about.mapping”文件中来实现的。例如,在 <install>/plugins/com.example.acme.acmefeature_1.0.0/about.mapping 中。“about.mapping”文件可能预先存在于 <product head> 输入中,或者可能需要在安装时由安装程序来创建。密钥是一些数字;“n”密钥的值代替了“aboutText”属性中的子串“{n}”。例如,如果许可证密钥是字段数值 0,则应该创建一个包含类似于“0=T42-24T-ME4U-U4ME”这一行的“about.mapping”文件。

N.B.“about.mapping”文件是一个 java.io.Properties 格式文件(带有“\”转义的 ISO 8859-1 字符编码)。当安装时的本机字符编码不同于 ISO 8859-1 时,安装程序负责将本机字符编码转换成 Unicode 和在需要的位置添加“\”转义字符。当字符串中包含特殊字符(例如,“\”)或者非拉丁字符时,则需要进行转义。例如,包含“希腊”字母的前 3 个字母的字段数值 1 将写成“1=\u03B1\u03B2\u03B3”。

在步骤 12 中,产品安装程序使用特殊的 -initialize 选项 [exact details TBD] 来启动产品可执行文件( <install>/acmeproduct.exe)。这将使 Eclipse 平台安静地执行所有耗时的首次处理并高速缓存结果。这样,当用户启动产品时,它将立即进入“开始营业”状态。

卸载程序行为

在卸载时,卸载程序应该以标准方式运行:

  1. 警告用户退出所有程序,尤其是正在卸载的产品
  2. 要求用户确认是否要卸载产品
  3. 从 <install> 目录中除去已安装的所有文件以及 <install>/eclipse/features 和 <install>/eclipse/plugins 中的所有文件(包括由除了此安装程序之外的伙伴放在其中的文件)(例如,由 Eclipse 更新管理器放置的文件)
  4. 除去产品可执行文件的桌面快捷方式
  5. 除去产品卸载程序的条目
  6. 通知未除去的任何文件的用户

当卸载产品时,应该删除在安装时存储的文件以及更新的功能部件和由 Eclipse 更新管理器创建的插件。要点:在卸载时,在 <install> 目录中可存在其它目录和文件,值得注意包含卸载产品时必须保留的重要数据的 <install>/eclipse/work查看编辑器的更新/<install>/eclipse/links/<install>/eclipse/platform.cfg。用户必须能够在同一位置卸载和重新安装一个产品而不丢失重要数据。

当已经安装了产品时的安装程序行为

当在用户的计算机上已经安装了产品时,安装程序应该允许对已安装的产品进行服务更新或版本升级。

在安装时,安装程序应该以标准方式运行:

  1. 警告用户退出所有程序,尤其是正在更新的产品
  2. 找到要更新的已安装产品,(如果需要,通过对现有产品安装搜索磁盘或者通过允许用户找到它来完成此操作)
  3. 确定此安装程序在何处是可兼容更新
  4. 如果适当的话,将要求用户提供已注册的所有者的姓名以及许可证密钥
  5. 显示产品的已更新许可证协议,并要求用户接受
  6. 要求用户确认有关更新的所有详细信息
  7. 对磁盘更新文件(参见下面的内容)
  8. 如果需要,则改变桌面快捷方式以运行产品可执行文件
  9. 应该将已修改或新添加的文件添加至卸载时要除去的文件的列表(如果可行的话)
  10. 企图显示产品发行说明(“readme”文件)

在步骤 2 中,直接包含名为“.eclipseproduct”的文件的“eclipse”目录可以识别已安装的产品。“eclipse”目录的父代是产品的安装目录(即,<install>/eclipse/.eclipseproduct)。应该对用户显示此标记文件中包含的信息以确认是否正在更新正确的产品(在用户的计算机上可能存在几个基于 Eclipse 的产品)。

在步骤 3 中,安装程序应该通过对 <install>/eclipse/features 目录中的子目录进行简单模式匹配来执行兼容性检查。例如,如果存在与“com.example.acme.otherfeature_1.0.1”相匹配的文件夹,则将确保已经对已安装的产品应用了某些服务更新。

在步骤 7 中,安装程序可能会删除或替换它最初安装的任何文件,并添加更多文件。要点:几个文件和目录(包括 <install>/eclipse/work查看编辑器的更新/<install>/eclipse/platform.cfg)可能与安装处于同一个位置,并且包含在升级产品时需要保留的重要数据文件。

在升级情况下,很可能 <install>/eclipse/plugins/ 下面的大多数文件都相同(对于 <install>/eclipse/features/,也是如此)。在 <install>/eclipse/plugins/ 中有很好的机会进行优化,因为当且仅当该目录下面的任何文件更改时,嵌入插件(或段)版本号的子目录名称才会更改。换句话说,如果升级之后此子目录还应该存在,则不需要涉及 <install>/eclipse/plugins/org.eclipse.ui_2.0.0/ 中的任何文件;如果要更改插件的任何文件,则会修订该插件的版本号,这将导致已升级的插件的文件安装在并行目录 <install>/eclipse/plugins/org.eclipse.ui_2.0.1/ 中。 

还要注意,在重新安装的情况下,一定不能使用 -initialize 来启动产品可执行文件,原因是这将丢失重要的用户配置数据。

对安装在别处的 JRE 进行关联

期望 JRE 位于 <install>/eclipse/jre/bin/javaw.exe。如果它位于别处,则应该在命令行上使用 -vm 选项来指定绝对路径(例如,-vm C:\j2jre1.3.0\jre\bin\javaw.exe)。在这种情况下,安装程序应该将此选项添加至它创建的桌面快捷方式的命令行。

扩展安装程序创建脚本

扩展表示一组可独立安装的功能部件及其插件,它们可以与同一计算机上安装的一个或多个基于 Eclipse 的产品相关联,并且可以从这些产品中来使用这些功能部件和插件。与产品相反,扩展不是自包含的;扩展不包括产品可执行文件、Eclipse 平台和 JRE。

在不失去普遍性的情况下,假定扩展由单个功能部件组成。安装程序创建脚本的第一个输入是一个目录(<extension>),该目录包含它的功能部件和插件。我们假定一个扩展没有与 Eclipse 相关的任何文件;如果有这种文件,则它们将放置在 <extension>/ 中而不是放置在 <extension>/eclipse/ 中。作为参考,此目录的框架结构为如下所示:

<extension>/
  eclipse/
    features/
      com.example.wiley.anvilfeature_1.0.0/
        feature.xml
    plugins/
       com.example.wiley.anvilfeature_1.0.0/
        plugin.xml
        about.ini
        about.properties
        about.mappings
       com.example.wiley.mainplugin_1.0.0/
       com.example.wiley.otherplugin_1.0.0/

<extension> 输入目录的精确内容确定哪些文件最终将安装在最终用户的计算机上。

安装程序创建脚本的最终输入是扩展的功能部件的标识和版本字符串(例如,“com.example.wiley.anvil”和“1.0.0”)。这些字符串对于安装程序具有特殊意义,它们出现在文件名和目录名以及在安装时创建的标记文件的内容中。

扩展安装程序在大多数方面与产品安装程序相似。下面突出显示了扩展安装程序有所不同的区域:

在安装时,安装程序以标准方式运行:

  1. 警告用户退出所有程序
  2. 介绍要安装的扩展
  3. 如果适当的话,将要求用户提供已注册的所有者的姓名以及许可证密钥
  4. 显示扩展的许可证协议,并要求用户接受
  5. 建议磁盘上的某个位置来安装扩展(但是允许用户覆盖此缺省值)
  6. 检查产品或另一扩展是否尚未存储在指定的位置
  7. 询问用户哪些产品要使用此扩展(搜索磁盘;浏览或跳过)
  8. (可选)确定扩展是否与所选择的产品兼容
  9. 要求用户确认有关安装的所有详细信息
  10. 创建标记文件以标记扩展安装的根
  11. 将文件复制到磁盘(参见下面的内容)
  12. 将已注册的所有者的姓名和许可证密钥插入到“关于”描述中
  13. 创建适当的条目以允许用户卸载扩展
  14. 编写所选择的每个产品中的链接文件以使扩展与产品相关联
  15. 企图显示扩展发行说明(“readme”文件)

如果在步骤 5 中指定的位置是 <install>,则在步骤 11 中,安装程序将把 <extension> 目录中的所有文件复制到 <install> 中。

输入文件 已安装的文件
<extension>/* <install>/*

对于步骤 7,任何 Eclipse 产品都可以是候选值。<product install>/eclipse/.eclipseproduct 文件可以识别基于 Eclipse 的产品;用户应该能够请求进行有限的磁盘搜索来查找已安装的产品(“搜索已安装的产品”按钮),或者将导航至包含产品的目录(即,“浏览”按钮)。

在步骤 8 中,安装程序应该通过对 <product install>/eclipse/features 目录中的子目录进行简单模式匹配来执行兼容性检查。例如,如果存在与“org.eclipse.jdt_2.* 相匹配的文件夹,则表示 JDT 包括在已安装的产品中。

在步骤 10 中创建的标记文件是 <install>/eclipse/.eclipseextension,使用它来标记已经将基于 Eclipse 的扩展安装到的目录,这主要用于扩展安装程序定位(对于产品的 .eclipseproduct 标记文件,情况类似)。此标记文件是一个 java.io.Properties 格式文件(带有“\”转义的 ISO 8859-1 字符编码),并且包含对用户标识扩展以及将基于 Eclipse 的一个扩展与另一个扩展区分开来的以下信息:

name=Wiley Anvil Enterprise Edition
id=com.example.wiley.anvilfeature
version=1.0.0

“id”和“version”属性的值是安装程序创建脚本的输入;扩展的名称大致可以推测出来并且准确性较高。(产品通常不会访问此标记文件;只有产品和扩展安装程序才会编写或读取它。)

在安装所有文件之后,安装目录的顶层结构将包含下列文件和子目录:

<install>/
  eclipse/
    .eclipseextension
    features/
    plugins/

与产品安装程序的唯一显著区别是扩展安装程序还要在已经安装在用户的计算机上的基于 Eclipse 的其它产品中创建链接文件。(这就使用户不必使用 Eclipse 更新管理器来手工关联每个产品中的新扩展。) 

在步骤 14 中创建的链接文件是 <product install>/eclipse/links/com.example.wiley.anvilfeature.link;即,该文件的名称与扩展的功能部件目录去掉版本号后缀获得的名称相同。链接文件是一个 java.io.Properties 格式文件(带有“\”转义的 ISO 8859-1 字符编码)。密钥是“path”,其值为已安装的扩展(<install>)的绝对路径;例如,看起来可能类似于“path=C:\\Program Files\\Wiley\\Anvil的一个条目。安装程序负责将本机字符编码转换成 Unicode 和在需要的位置添加“\”转义字符。通常需要进行转义,原因是 <install> 通常包含特殊字符(例如“\”)并且在它们的名称中可能涉及到带有非拉丁字符的目录。当产品启动时,它将读取链接文件。安装程序保留它所创建的任何链接文件的记录,于是,当更新或卸载扩展时,就可以找到这些记录。

卸载程序行为

在卸载时,卸载程序应该以标准方式运行:

  1. 警告用户退出所有程序,尤其是使用正在卸载的扩展的那些产品
  2. 要求用户确认是否要卸载扩展
  3. 从 <install> 目录中除去已安装的所有文件以及 <install>/eclipse/features 和 <install>/eclipse/plugins 中的所有文件(包括由除了此安装程序之外的伙伴放在其中的文件)(例如,由 Eclipse 更新管理器放置的文件)
  4. 如果可能的话,从已经添加了链接文件的任何产品中除去该链接文件
  5. 除去扩展卸载程序的条目
  6. 通知未除去的任何文件的用户

当卸载了扩展时,所有插件和功能部件文件都应该删除;并且在这些子目录中不会保留任何重要数据文件。这允许用户彻底地卸载扩展(包括由 Eclipse 更新管理器所作的任何更新)。

当已经安装了扩展时的安装程序行为

当在用户的计算机上已经安装了扩展时,安装程序应该允许对已安装的扩展进行服务更新或版本升级。

在安装时,安装程序应该以标准方式运行:

  1. 警告用户退出所有程序,尤其是使用正在更新的扩展的那些产品
  2. 找到要更新的已安装的扩展,(如果需要,通过对现有扩展安装搜索磁盘或者通过允许用户找到它来完成此操作)
  3. 确定此安装程序在何处是可兼容更新
  4. 如果适当的话,将要求用户提供已注册的所有者的姓名以及许可证密钥
  5. 显示产品的已更新许可证协议,并要求用户接受
  6. 要求用户确认有关更新的所有详细信息
  7. 更新磁盘上的文件(参见下面的内容)
  8. 应该将已修改或新添加的文件添加至卸载时要除去的文件的列表(如果可行的话)
  9. 企图显示扩展发行说明(“readme”文件)

在步骤 2 中,直接包含名为“.eclipseextension”的文件的“eclipse”目录可以识别已安装的扩展。“eclipse”目录的父代是扩展的安装目录(即,<install>/eclipse/.eclipseextension)。应该对用户显示此标记文件中包含的信息以确认是否正在更新正确的扩展(在用户的计算机上可能存在几个基于 Eclipse 的扩展)。

在步骤 7 中,安装程序不应该删除或覆盖它最初安装的任何文件;相反,它只应该为新版本的功能部件和插件添加文件,并尽可能重写标记文件 <install>/eclipse/.eclipseextension。保留旧版本可以使用户选择取消更新。与升级产品安装的情况相同,如果升级之后此子目录还应该存在,则不需要涉及 <install>/eclipse/plugins/com.example.wiley.otherplugin_1.0.0/ 中的任何文件;如果要更改插件的任何文件,则会修订该插件的版本号,这将导致已升级的插件的文件安装在并行目录 <install>/eclipse/plugins/com.example.wiley.otherplugin_1.0.1/ 中。 

Copyright IBM Corporation and others 2000, 2003.