Eclipse 2.1 与 3.0 之间的不兼容性

Eclipse 在 2.1 与 3.0 之间以不兼容的方式进行了更改,它们会影响插件。下列各项描述了已更改的区域,并且提供了有关从 2.1 插件迁移到 3.0 的指示信息。注意,如果您在 3.0 上运行 2.1 插件时遇到了问题,只需参阅本文档。

  1. 插件清单版本
  2. 重构平台用户界面插件
  3. 重构平台核心运行时插件
  4. 除去 Xerces 插件
  5. Eclipse 3.0 具有更高的并发性
  6. 对 IFiles 打开编辑器
  7. 编辑器转至标记
  8. 编辑器启动程序
  9. 编辑器注册表
  10. 工作台标记帮助注册表
  11. 文本编辑器文档提供程序
  12. 文本编辑器
  13. 无头注释支持
  14. 控制台视图
  15. Java 断点侦听器
  16. 用户界面线程中的剪贴板访问权
  17. 按下键事件
  18. 用 Tab 键遍历定制控件
  19. SWT 表和树窗口小部件中的选择事件顺序
  20. 状态对象中新的严重性级别
  21. 与构建相关的资源更改通知
  22. 工作空间操作期间的中间通知
  23. URL 流处理程序扩展
  24. 类装入顺序
  25. 未设置类装入器保护域
  26. PluginModel 对象数据类型转换
  27. ILibrary 实现不完整
  28. 与 URL 的格式有关的无效假定
  29. 已移动/删除的 BootLoader 方法
  30. 插件导出不自动包括插件的 JAR
  31. 重新导出运行时 API
  32. 平台上的插件解析方法
  33. 由段提供的插件库
  34. 对构建脚本的更改
  35. 对 PDE 构建 Ant 任务的更改
  36. 对 eclipse.build Ant 任务的更改
  37. 对 eclipse.fetch Ant 任务的更改
  38. 替换 install.ini

1. 插件清单版本

已经将用于插件(和插件段)的清单文件的头更改为包括一个新行,该行标识了适当的插件清单版本。在 3.0 之前,插件未包含这些 <?eclipse ...?> 行的其中一行;在 3.0 之后,插件必须始终都包含其中一行。此更改是为了让 Eclipse 运行时能够准确地识别尚未移植到 3.0 的 3.0 之前的插件,以便它可以为这种插件自动提供更强的二进制兼容性。以下是 plugin.xml 文件的一般格式(fragment.xml 是相似的):

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin ...>
    ...
</plugin>

由 PDE 3.0 创建的插件清单自动就具有此格式。强烈建议您使用 PDE 插件迁移工具。它将指示行自动插入到 2.1 插件和插件段的清单中,并解决此处描述的许多其它更改。

如果您(通过手工或者使用 PDE)将此伪指令添加至 plugin.xml,则还必须更新文件以显式列示它依赖于的插件。例如,在 Eclipse 3.0 之前,对于 org.eclipse.core.runtime 和 org.eclipse.core.boot 的依赖性是隐式的。在 3.0 中,不再需要 org.eclipse.core.boot,开发者必须适当地选择 org.eclipse.core.runtime 或 org.eclipse.core.runtime.compatibility(或者这两者都不选)。

注:这是其中一项不兼容性,它不会影响 Eclipse 3.0 如何运行 2.1 二进制插件。

2. 重构平台用户界面插件

org.eclipse.ui 插件(曾经是主要平台用户界面插件)现在为通用(即,不是特定于 IDE 的)工作台只提供了 API 和扩展点。可选的和特定于 IDE 的 API 和扩展点已经移动到其它插件。

此更改具有两个方面的影响:(1) 已移动的 org.eclipse.ui 扩展点具有新的扩展点标识;(2) 必需插件的列表已更改。

下表中的 org.eclipse.ui 扩展点已移至其它插件,导致它们的扩展点标识发生了更改。如果现有插件为已移动的扩展点添加一个扩展,则必须更改插件清单文件中的 <extension> 元素的“point”属性中的引用,以表示相应的新扩展点标识。PDE 插件迁移工具进行了这些修订。

注:这是其中一项不兼容性,它不会影响 Eclipse 3.0 如何运行 2.1 二进制插件。Eclipse 3.0 运行时将自动检测 3.0 之前的插件(通过在插件清单中去掉前面提到的 <?eclipse version="3.0"?> 这一行),并自动补偿这些扩展点和插件依赖项更改。

旧的扩展点标识

新的扩展点标识

org.eclipse.ui.markerHelp org.eclipse.ui.ide.markerHelp
org.eclipse.ui.markerImageProviders org.eclipse.ui.ide.markerImageProviders
org.eclipse.ui.markerResolution org.eclipse.ui.ide.markerResolution
org.eclipse.ui.projectNatureImages org.eclipse.ui.ide.projectNatureImages
org.eclipse.ui.resourceFilters org.eclipse.ui.ide.resourceFilters
org.eclipse.ui.markerUpdaters org.eclipse.ui.editors.markerUpdaters
org.eclipse.ui.documentProviders org.eclipse.ui.editors.documentProviders
org.eclipse.ui.workbench.texteditor.
markerAnnotationSpecification
org.eclipse.ui.editors.markerAnnotationSpecification

下表列示了先前是由 org.eclipse.ui 插件提供的但是已移至不同插件中的 API 包。(API 包、类、字段和方法的名称未更改。)在某些情况下,API 包现在分散在多个插件中。因为对于任何给定插件可视的 API 类是由该插件的必需插件的列表来确定的,所以,这些更改可能要求调整现有插件的清单中的“<requires>”元素,以重新获得对 API 类的访问权。

此更改只会影响依赖于 org.eclipse.ui 插件的那些插件 (即,在插件清单的 <requires> 一节包括 <import plugin="org.eclipse.ui"/>);所有其它插件将不受影响。如果插件受到了影响,则您可能需要更改 <import> 元素,或者添加其它 <import> 元素,以便您的插件需要的所有 API 类都在作用域内。强烈建议插件只声明与它实际使用的插件的依赖性。包括不必要的依赖性将降低运行时性能,这是因为 Java 类装入器必须搜索所有依赖项中的类。(PDE 插件迁移工具将修订依赖性,并帮助确定最小集合。)

API 包

2.1 插件

相应的 3.0 插件

org.eclipse.jface.text.* org.eclipse.ui org.eclipse.jface.text
org.eclipse.text.* org.eclipse.ui org.eclipse.jface.text
org.eclipse.ui org.eclipse.ui org.eclipse.ui 和 org.eclipse.ui.ide
org.eclipse.ui.actions org.eclipse.ui org.eclipse.ui 和 org.eclipse.ui.ide
org.eclipse.ui.dialogs org.eclipse.ui org.eclipse.ui 和 org.eclipse.ui.ide
org.eclipse.ui.editors.* org.eclipse.ui org.eclipse.ui.editor
org.eclipse.ui.model org.eclipse.ui org.eclipse.ui 和 org.eclipse.ui.ide
org.eclipse.ui.part org.eclipse.ui org.eclipse.ui 和 org.eclipse.ui.ide
org.eclipse.ui.texteditor org.eclipse.ui org.eclipse.ui.workbench.texteditor 和 org.eclipse.ui.editors
org.eclipse.ui.texteditor.* org.eclipse.ui org.eclipse.ui.workbench.texteditor
org.eclipse.ui.views.bookmarkexplorer org.eclipse.ui org.eclipse.ui.ide
org.eclipse.ui.views.contentoutline org.eclipse.ui org.eclipse.ui.views
org.eclipse.ui.views.markers org.eclipse.ui org.eclipse.ui.ide
org.eclipse.ui.views.navigator org.eclipse.ui org.eclipse.ui.ide
org.eclipse.ui.views.properties org.eclipse.ui org.eclipse.ui.views
org.eclipse.ui.views.tasklist org.eclipse.ui org.eclipse.ui.ide
org.eclipse.ui.wizards.datatransfer org.eclipse.ui org.eclipse.ui.ide
org.eclipse.ui.wizards.newresource org.eclipse.ui org.eclipse.ui.ide

3. 重构平台核心运行时插件

“Eclipse 3.0 平台运行时”是基于 OSGi 的,它强制更改 org.eclipse.core.runtime 和 org.eclipse.core.boot 这两个“平台运行时”插件的结构。

新的 org.eclipse.core.runtime.compatibility 插件提供了旧的 API 与新的 API 之间的实现桥梁,它是先前在 org.eclipse.core.runtime 和 org.eclipse.core.boot 中找到的许多过时 API 的新归宿。“平台运行时”扩展点不受重构的影响。

当将现有插件迁移到 3.0 时,需要更新插件的清单,以反映“Eclipse 平台运行时”插件的新结构。如果需要,PDE 插件清单迁移工具将为 org.eclipse.core.runtime.compatibility 添加依赖项。

还要注意,如果您(使用 <?eclipse version="3.0"?>)将插件标记为 3.0,并且插件定义了插件类,则必须在插件清单中显式地 <import plugin="org.eclipse.core.runtime.compatibility"/>,或者要确保插件类定义缺省构造函数。

注:这是其中一项不兼容性,它不会影响 Eclipse 3.0 如何运行 2.1 二进制插件。Eclipse 3.0 行时将自动检测 3.0 之前的插件(通过在插件清单中去掉 <?eclipse version="3.0"?> 这一行),并自动补偿对“平台运行时”的这些更改。

4. 除去 Xerces 插件

不再需要 org.eclipse.xerces 插件,已将它删除。XML 解析支持已内置到 J2SE 1.4 中,如果存在 Xerces 插件则会产生类装入器冲突。先前由 org.eclipse.xerces 插件提供的 javax.xml.parsers、org.w3c.dom.* 和 org.xml.sax.* API 包现在可从 J2SE 库中获得。

如果您的插件需要 org.eclipse.xerces 插件,则必须更改插件清单以除去这个已声明的依赖性。完成之后,无须进一步更改就可以编译和运行该插件的代码了。

当在标准的 Eclipse 3.0 配置中运行时,已声明与 org.eclipse.xerces 插件的依赖性的 2.1 二进制插件将丢失必备软件。其结果是将不会激活该插件。

5. Eclipse 3.0 具有更高的并发性

在 Eclipse 3.0 之前,Eclipse 基本上是在单线程中运行的。大多数 API 方法和扩展点在用户界面线程或者在从进度对话框中衍生的将阻塞用户界面线程的线程中运行。除了要确保所有用户界面活动都发生在用户界面线程中之外,大多数插件编写者不必太担心线程安全。在 Eclipse 3.0 中,通常具有更多并发性。现在,许多操作是在后台线程中进行的,它们可以与其它线程(包括用户界面线程)同时运行。其代码在后台线程中运行的所有插件现在必须知道它们的代码的线程安全。

除了使用 org.eclipse.core.runtime.jobs API 在后台显式运行操作的插件之外,还有几个平台 API 设施和扩展点利用后台线程。挂接到这些设施中的插件需要确保它们的代码是线程安全的。下表总结了 Eclipse 3.0 中在后台线程运行它们的某些代码或所有代码的 API 和扩展点:

扩展点或 API 类

注释

org.eclipse.core.runtime.IRegistryChangeListener Eclipse 3.0 版新增内容,在后台运行
org.eclipse.core.resources.IResourceChangeListener AUTO_BUILD 事件现在在后台进行
org.eclipse.core.resources.builders(扩展点) 自动构建现在在后台进行
org.eclipse.core.resources.ISaveParticipant SNAPSHOT 现在在后台进行
org.eclipse.ui.workbench.texteditor.quickdiffReferenceProvider(扩展点) Eclipse 3.0 版新增内容,在后台运行
org.eclipse.ui.decorators(扩展点) 在 Eclipse 2.1 中就已经在后台进行
org.eclipse.ui.startup(扩展点) 在 Eclipse 2.1 中就已经在后台进行
org.eclipse.team.core.org.eclipse.team.core.repository(扩展点) 许多操作现在在后台进行
org.eclipse.team.ui.synchronizeParticipants(扩展点) Eclipse 3.0 版新增内容,在后台运行
org.eclipse.debug.core.launchConfigurationTypes(扩展点) 现在在后台运行
org.eclipse.jdt.core.IElementChangedListener ElementChangedEvent.PRE_AUTO_BUILD 现在在后台运行,POST_RECONCILE 已经在后台运行

可以采用多种策略使代码具有线程安全。常见的解决方案是确保所有工作都在用户界面线程中进行,从而确保序列化执行。对于不进行大量消耗 CPU 的处理的用户界面插件来说,这是一种常见方法。当采用这种方法时,务必清楚 Display.syncExec 固有的死锁风险。Display.asyncExec 通常会更安全,这是因为它不会产生死锁风险,但是它无法精确控制何时执行代码。

生成线程安全代码的其它技术包括:

6. 对 IFiles 打开编辑器

从 org.eclipse.ui.IWorkbenchPage 接口中删除了下列方法。IWorkbenchPage 是在通用工作台中声明的,但是这些方法本来就是特定于资源的。

这些 IWorkbenchPage.openEditor 方法的客户机应该调用在 org.eclipse.ui.ide.IDE 类(该类在 org.eclipse.ui.ide 插件中)中声明的公用静态方法。

这些 IWorkbenchPage.openSystemEditor(IFile) 方法的客户机应该使用新的 FileEditorInput(IFile) 将 IFile 转换为 IEditorInput,然后调用 openEditor(IEditorInput,String) 方法。换句话说,就是将 page.openSystemEditor(file) 改写为 page.openEditor(new FileEditorInput(file) 和 IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID)。注:使用编辑器标识 IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID 的客户机 必须传递编辑器输入,它实现 org.eclipse.ui.IPathEditorInput(这是 FileEditorInput 执行的任务)。

注:这是其中一项不兼容性,它不会影响 Eclipse 3.0 如何运行 2.1 二进制插件。Eclipse 3.0 包括二进制运行时兼容性机制,该机制确保使用任何已删除的 openEditor 和 openSystemEditor 方法的现有 2.1 插件二进制文件继续象在 2.1 中那样工作,无论此 API 是否发生更改都是如此。(被删除的方法实际上是通过 org.eclipse.ui.workbench.compatibility 段“添加回去”的。)

7. 编辑器转至标记

从 org.eclipse.ui.IEditorPart 接口中删除了以下方法。IEditorPart 是在通用工作台中声明的,但是该方法本来就是特定于资源的。

相应的方法也从 org.eclipse.ui.part 包中实现 IEditorPart 的类中删除了,这些方法是:EditorPart、MultiEditor、MultiPageEditorPart 和 MultiPageEditor。 

调用此方法的客户机应该测试编辑器部件是否实现或者适应 org.eclipse.ui.ide.IGotoMarker(它在 org.eclipse.ui.ide 插件中),如果是这样,则调用 gotoMarker(IMarker)。IDE 类可以采用以下这种很方便的方法来完成此任务:IDE.gotoMarker(editor, marker);

实现可以根据 IMarker 信息来定位它本身的编辑器的客户机应该实现或适应 org.eclipse.ui.ide.IGotoMarker。

由于 IGotoMarker 的唯一方法是 gotoMarker(IMarker),并且还与旧的 IEditorPart.gotoMarker(IMarker) 具有相同的特征符和规范,因此,只需通过将 IGotoMarker 包括在类定义的实现子句中就可以使现有编辑器实现适应此更改。

当在标准的 Eclipse 3.0 配置中运行时,具有调用此方法的代码的 2.1 二进制插件将产生类链接错误异常。

8. 编辑器启动程序

编辑器启动程序接口 org.eclipse.ui.IEditorLauncher 是通过添加外部编辑器的插件实现的。从此接口中除去了以下方法。IEditorLauncher 是在通用工作台中声明的,但是该方法本来就是特定于资源的。

它被替换为:

调用 IEditorLauncher.open(file) 的客户机应该调用 IEditorLauncher.open(file.getLocation())。实现此接口的客户机应该将它们的 open(IFile) 的实现替换为 open(IPath) 的实现(或者扩充它们的实现)。

当在标准的 Eclipse 3.0 配置中运行时,具有调用此方法的代码的 2.1 二进制插件将产生类链接错误异常。

9. 编辑器注册表

从 org.eclipse.ui.IEditorRegistry 接口中除去了下列方法。IEditorRegistry 是在通用工作台中声明的,但是这些方法本来就是特定于资源的。

调用 getEditors(file) 或 getImageDescriptor(file) 的客户机应该调用等效的“字符串”方法: 调用 setDefaultEditor(IFile file, String editorId) 和 getDefaultEditor(IFile file) 的客户机应该调用在 org.eclipse.ui.ide.IDE 类(该类在 org.eclipse.ui.ide 插件中)声明的相应的公用静态方法: 另外,更改了 IEditorRegistrygetDefaultEditor() 方法的 API 合同。此方法(现在也不推荐使用了)将始终返回“系统外部编辑器”编辑器描述符。此更改将影响假定返回的缺省编辑器是文本编辑器的那些客户机。

具有表示系统外部编辑器和系统适当位置编辑器标识(SYSTEM_EXTERNAL_EDITOR_ID 和 SYSTEM_INPLACE_EDITOR_ID)的新常量。这两个编辑器需要实现或适应 org.eclipse.ui.IPathEditorInput 的编辑器输入。注意,适当位置编辑器描述符将不存在于不支持适当位置编辑的 Eclipse 配置中。

10. 工作台标记帮助注册表

从 org.eclipse.ui.IWorkbench 接口中删除了以下方法。IWorkbench 是在通用工作台中声明的,但是该方法本来就是特定于资源的。

IWorkbench.getMarkerHelpRegistry() 的客户机应该调用公用静态方法 org.eclipse.ui.ide.IDE.getMarkerHelpRegistry()(在 org.eclipse.ui.ide 插件中)。

当在标准的 Eclipse 3.0 配置中运行时,具有调用此方法的代码的 2.1 二进制插件将产生异常。

11. 文本编辑器文档提供程序

为了使 org.eclipse.ui.texteditor.AbstractTextEditor 与 IFile 无关,org.eclipse.ui.texteditor.AbstractDocumentProvider 引入了文档提供程序操作(DocumentProviderOperation)和文档提供程序操作运行程序(IRunnableContext)的概念。当请求执行复位、保存或同步时,AbstractDocumentProvider 将创建文档提供程序操作并使用操作运行程序来执行它们。可以通过 getOperationRunner 方法由子类提供可运行程序上下文。以下是对客户机必须适应的更改的总结:

AbstractDocumentProvider 子类 org.eclipse.ui.editors.text.StorageDocumentProvider 实现 getOperationRunner 方法以始终返回 null。这意味着 StorageDocumentProvider 的子类不应该受此更改影响。

StorageDocumentProvider 子类 org.eclipse.ui.editors.text.FileDocumentProvider 实现 getOperationRunner 方法,该方法返回用于在 WorkspaceModifyOperation 中执行给定的 DocumentProviderOperations 的 IRunnableContext。对 FileDocumentProvider 的其它更改包括:

12. 文本编辑器

对 org.eclipse.ui.texteditor.AbstractTextEditor 所作的更改包括:

AbstractTextEditor 子类 org.eclipse.ui.texteditor.StatusTextEditor 提供了谓词方法 isErrorStatus(IStatus)。可以覆盖子类,以便决定是否认为给定的状态是一个错误。

对 org.eclipse.ui.editors.text.AbstractDecoratedTextEditor 所作的更改:

13. 无头注释支持

作为无头注释支持的简介的一部分,对注释进行了下列更改:

        org.eclipse.jface.text.source.Annotation 
        org.eclipse.jface.text.source.AnnotationModel 
        org.eclipse.jface.text.source.AnnotationModelEvent 
        org.eclipse.jface.text.source.IAnnotationModel 
        org.eclipse.jface.text.source.IAnnotationModelListener 
        org.eclipse.jface.text.source.IAnnotationModelListenerExtension

14. “控制台”视图

Eclipse 3.0 具有新的通用控制台支持。通过“窗口”>“显示视图”>“基本”>“控制台”可以获得通用控制台,Eclipse 调试和 Ant 集成将使用通用控制台。

控制台的视图标识已从 org.eclipse.debug.ui.ConsoleView 更改为 org.eclipse.ui.console.ConsoleView。使用程序打开控制台的 2.1 插件将不成功,因为旧的视图不再存在。

15. Java 断点侦听器

在 3.0 中,org.eclipse.jdt.debug.core.IJavaBreakpointListener.breakpointHit(IJavaBreakpoint, IJavaThread) 和 installingBreakpoing(IJavaTarget, IJavaBreakpoint, IJavaType) 方法的返回类型已从 boolean 更改为 int,以允许侦听器表决“不关心”。在 3.0 之前的发行版中,当遇到断点时,侦听器只能表决“暂挂”或“不暂挂”,当将安装断点时,只能表决“安装”或“不安装”。在 3.0 中,对于这些通知中的任一通知,侦听器还可以表决“不关心”。这允许客户机在它们关心的情况下只作出决定性的表决。对于“断点击中”通知,如果任何侦听器都表决“暂挂”或者所有侦听器都表决“不关心”,则断点将被暂挂,如果至少有一个侦听器表决“不暂挂”并且没有侦听器表决“暂挂”,则将不会暂挂断点。类似地,对于“断点安装”通知,如果任何侦听器都表决安装,或者所有侦听器都表决“不关心”,则将安装断点,如果至少有一个侦听器表决“不安装”并且没有侦听器表决“安装”,则将不会安装断点。通常,实现器应该返回 DONT_CARE,除非它们无论如何都具有明确的意见。一定要记住,例如,表决“暂挂”将覆盖任何其它侦听器的“不暂挂”表决。

IJavaBreakpointListener 接口是由在 Java 代码中创建断点或者对 Java 代码中的断点作出反应的客户机实现的。可能有一些客户机超越了 JDT 本身,保存报告了此更改纠正的问题(bug 37760)的客户机。这是对实现 IJavaBreakpointListener 接口的现有代码的突破性更改。在 3.0 中编译或运行此代码之前,需要修改它以返回适当的整数值。

16. 用户界面线程中的剪贴板访问权

在 3.0 之前,默许 SWT 类 org.eclipse.swt.dnd.Clipboard 的方法在除了用户界面线程之外的线程中运行。这种疏忽将导致在 GTK 上发生故障,因为在 GTK 上操作系统要求所有剪贴板交互都在用户界面线程中执行。这种疏忽先前并未暴露出来,这是因为许多应用程序是单线程的,并且在 Windows 上接收它们的大多数测试。为了使“剪贴板 API”持久存在并且可以跨平台操作,在 3.0 中,已经更改了所有“剪贴板 API”方法的规范和实现,以便在从非用户界面线程中调用时抛出 SWT 异常(ERROR_THREAD_INVALID_ACCESS)。剪贴板服务通常是由诸如文本编辑器的 Eclipse 组件自动提供的,从而使许多客户机与此重要更改隔离开。毕竟直接利用剪贴板的现有代码应该确保对正确的线程调用 API 方法,适当的时候使用 Display.asyncExec 或 syncExec 来将访问移入用户界面线程中。

17. 按下键事件

在 3.0 中,在操作系统中完成工作之前 SWT 就会报告按下键事件。这比在 3.0 之前报告得更早。进行此更改以支持 Eclipse 中的键绑定,在任何窗口小部件有机会处理字符之前,需要拦截键事件。对于直接处理低级 org.eclipse.swt.SWT.KeyDown 事件的代码来说,此更改的效果是很明显的。例如,当文本小窗口的侦听器接收到按下键事件时,窗口小部件的内容(getText())将还不会包括刚按下的键 (而在 3.0 之前,就会包括刚按下的键)。从包括当前键的窗口小部件中获取完整文本的建议方法是处理更高级别的 SWT.Modify 或 SWT.Verify 事件,而不是处理低级的 SWT.KeyDown 事件;已经按这样做的代码将不受此更改的影响。

18. 用 Tab 键遍历定制控件

在 3.0 之前,当焦点位于 SWT 类 org.eclipse.swt.widgets.Canvas 或者它的其中一个子类(包括定制窗口小部件)上时,按 Ctrl+Tab、Shift+Tab、Ctrl+PgUp 或 Ctrl+PgDn 将自动触发 遍历至下一个/前一个窗口小部件而不会报告键事件。未指定此行为,并且违背了画布可以看到在它们中输入的每个键这一规则。处理遍历的正确方法应该是注册遍历侦听器。为了正确支持 3.0 中的 Eclipse 键绑定而更改了缺省行为,以便画布现在可以看见 Ctrl+Tab、Shift+Tab、Ctrl+PgUp 和 Ctrl+PgDn 键事件,而不是进行遍历。如果您使用行画布或者定义画布的子类,则务必注册遍历侦听器。

19. SWT 表和树窗口小部件中的选择事件顺序

用鼠标选择 SWT 类 org.eclipse.swt.widgets.Table 和树中的项 在所有操作环境中都将生成事件序列 MouseDown-Selection-MouseUp。类似地,用键盘选择时在所有操作环境中都将生成事件序列 KeyDown-Selection-KeyUp。在 3.0 之前,事件顺序是不一致的,Motif 和 Photon 与其它事件存在差别,始终都将首先报告“选择”事件(即,Selection-MouseDown-MouseUp 或 Selection-KeyDown-KeyUp)。在 3.0 中,已经将 Motif 和 Photon 的事件顺序更改为与其它事件相匹配。在 {Windows, GTK} 和 {Motif, Photon} 上正确工作的现有代码可能不会受影响。但是,最好检查一下您的代码,以确保它不依赖于无效的事件顺序。

20. 状态对象中新的严重性级别

org.eclipse.core.runtime.IStatus 有一个新的严重性常量 IStatus.CANCEL,可以用它来指示取消。添加此严重性常量会影响依赖于一组可能的严重性 (这组严重性仅限于 IStatus.OKINFOWARNINGERROR)的 IStatus.getSeverity() 的调用者。getSeverity 的调用者应该更新它们的代码以包括新的严重性。

21. 与构建相关的资源更改通知

在 Eclipse 3.0 中,工作空间自动构建现在将在后台线程中进行。这要求对 org.eclipse.core.resources.IResourceChangeEvent 进行 API 合同更改。IResourceChangeEvent 的合同先前保证所有工作空间更改的事件按以下顺序排序:

  1. PRE_DELETEPRE_CLOSE 事件通知(如果适用)
  2. 执行操作
  3. PRE_AUTO_BUILD 事件通知
  4. 如果打开了自动构建,则执行增量式工作空间构建
  5. POST_AUTO_BUILD 事件通知
  6. POST_CHANGE 事件通知

现在,自动构建是在后台运行的,对于 AUTO_BUILD 事件与 POST_CHANGE 事件之间的暂存关系不再有任何保证。在 Eclipse 3.0 中,从操作中除去了以上结构中的步骤 3 到步骤 5。获得的图形为如下所示:

  1. PRE_DELETEPRE_CLOSE 事件通知(如果适用)
  2. 执行操作
  3. POST_CHANGE 事件通知

平台将定期执行后台工作空间构建操作。注意,无论自动构建是打开还是关闭的,都将发生这种情况。将不会指定何时进行此构建操作的精确计时。构建操作的结构看起来将为如下所示:

  1. PRE_BUILD 事件通知(PRE_BUILDPRE_AUTO_BUILD 的新名称)
  2. 如果打开了自动构建,则执行增量式工作空间构建
  3. POST_BUILD 事件通知(POST_BUILDPOST_AUTO_BUILD 的新名称)
  4. POST_CHANGE 事件通知

自动构建侦听器接收到的增量的参考点将与 post-change 侦听器不同。构建侦听器将接收到自从上次构建操作结束以来所有更改的通知。Post-change 侦听器将接收到一个增量,该增量描述自从上次发出 post-change 通知以来进行的所有更改。这种新结构保留了自从 Eclipse 1.0 以来资源更改侦听器一直具有的三项特征:

但是,与此方法具有一些重要区别。在 Eclipse 3.0 之前,始终在调用 POST_CHANGE 侦听器之前调用自动构建侦听器。因此,自动构建侦听器接收到的增量始终是 POST_CHANGE 侦听器接收到的增量的子集。这种关系现在基本上颠倒了。自动构建侦听器将接收的增量是自从上次后台构建结束以来提供给 POST_CHANGE 侦听器的所有增量的超集。与以前一样,将允许自动构建侦听器修改工作空间,而 post-change 侦听器将不允许修改工作空间。

当完成工作空间更改操作时,将不再是已经通知了 AUTO_BUILD 事件侦听器。使用 IWorkspace.addResourceChangeListener(IResourceChangeListener) 来注册资源更改侦听器的客户机代码可能不会受此更改的影响,这是因为 AUTO_BUILD 事件决不会报告给这些侦听器。但是,使用 IWorkspace.addResourceChangeListener(IResourceChangeListener,int) 并且 指定包括 AUTO_BUILD 事件的事件掩码的客户机 可能会被此更改破坏(如果它们假定了自动构建侦听器何时运行或者它们运行于哪个线程)。例如,如果自动构建侦听器正在更新域模型以反映对工作空间的更改,则当工作空间更改操作返回时可能尚未进行此更新。值得注意的是,只有用户界面级别的代码才会受这种方式影响。可以在 IWorkspaceRunnable 的作用域内调用通过 API 调用的核心级别的代码,所以它从来不敢肯定何时将调用资源更改侦听器。如果需要在完成操作之前发出通知,则对于此缺陷的建议修正方法是使用 POST_CHANGE 而不是使用构建侦听器。

22. 工作空间操作期间的中间通知

将不再保证在 IWorkspaceRunnable 的动态作用域期间进行的所有资源更改将在单个通知中进行批处理。此机制仍然可以用于批处理更改,以避免不必要的构建和通知,但是,平台现在可能会决定在操作期间执行通知。此 API 合同更改不可能是对现有客户机的突破性更改。它相当于平台决定在长时间运行的操作期间定期调用 IWorkspace.checkpoint。要进行此更改的原因在于,现在可能有多个线程同时修改工作空间。当一个线程完成修改工作空间时,即使其它操作尚未完成,也需要发出通知以防止发生响应性问题。此更改还允许用户在操作完成之前就开始处理一组资源。例如,用户现在可以开始浏览项目中仍然处于检出过程中的文件。新方法 IWorkspace.run(IWorkspaceRunnable, ISchedulingRule, int, IProgressMonitor) 具有一个可选标志 AVOID_UPDATE,可以将它的操作用作对平台的提示,以指定是否期望进行定期更新。

23. URL 流处理程序扩展

受影响的对象:org.eclipse.core.runtime.urlHandlers 扩展点添加扩展的插件。

描述: org.eclipse.core.runtime.urlHandlers 扩展点的合同已更改为使用由 OSGi 提供的“URL 流处理程序”服务。OSGi 支持优于 Eclipse 2.1 中的支持,并正确地处理了动态处理程序。由于基本 Java URL 处理程序机制具有各种设计问题,因此,向 OSGi 处理程序服务注册的 URLStreamHandlers 必须实现 org.osgi.service.url.URLStreamHandlerService

需要的操作:以前,处理程序类必须实现 java.net.URLStreamHandler 并扩展 urlHandlers 扩展点。该扩展点不再受支持,并且必须更新处理程序以实现 org.osgi.service.url.URLStreamHandlerService 接口。OSGi 框架提供了一个抽象基本类(org.osgi.service.url.AbstractURLStreamHandlerService),可以无足轻重地对它划分子类以完成此任务。

现在,插件必须通过将它们的处理程序作为服务来注册来注册处理程序,而不是使用扩展点来注册处理程序。例如,

    Hashtable properties = new Hashtable(1);
    properties.put(URLConstants.URL_HANDLER_PROTOCOL, new String[] {MyHandler.PROTOCOL});
    String serviceClass = URLStreamHandlerService.class.getName();
    context.registerService(serviceClass, new MyHandler(), properties);

24. 类装入顺序

受影响的对象:这样的插件将受影响:它所提供的包也是由其它插件提供的。会受到此更改影响的插件数量非常有限,受影响的某些插件实际上将获得好处(请参阅下面的内容)。

描述:在 Eclipse 2.x 中,类装入器按以下顺序搜索类:(1) 查阅父代类装入器(实际上,这是 Java 引导类装入器),然后 (2) 查阅它自己的类路径内容 最后 (3) 按声明的顺序查阅它的所有必备软件。OSGi 对此模型提供了优化。在此方法中,类装入器将查阅 (1) 父代类装入器(然后,有效地查阅 Java 引导类装入器),然后再查阅 (2a) 正在查阅的包中的添加类知道的单个必备软件,或者查阅 (2b) 期望类的它自己的类路径条目。

类装入器根据它已导入的和必需的包来确定是否查阅它自己或者它的必备软件。对于传统插件,此信息是从插件内容中推断出来的,而对于具有显式 OSGi bundle 清单的插件,此信息是直接指定的。在任何一种情况下,都要先验哪些类装入器将为哪些包提供类。这样做不但可以提高性能,而且还解决了多个必备软件添加相同的类这个伤脑筋的问题。

以 Xerces 和 Xalan 为例,它们两个都包含来自 org.xml 包中的各种类。如果使用第一种方法,Xerces 插件将看到这些类的副本,而 Xalan 插件将看到它们的副本。由于这些插件需要进行通信,因此发生了 ClassCastExceptions。如果使用第二种方法,这两个插件只有其中一个插件添加重复的类,并且两个插件将看到相同的副本。

需要的操作:需要的操作取决于用例的细节。受影响的开发者需要查看它们的类路径并解决可能发生的任何冲突。

25. 未设置类装入器保护域

受影响的对象:期望始终设置它们的类装入器的保护域的插件。

描述:在 Eclipse 2.1 中,插件类装入器是 java.security.SecureClassloaders,因此,始终设置了保护域。在 Eclipse 3.0 中,类装入器不会扩展 SecureClassloader,并且仅当打开了 Java 安全性时(不是正常情况)才会设置保护域。

需要的操作:需要的操作将取决于插件使用保护域所采用的方案。

26. PluginModel 对象数据类型转换

受影响的对象:将 org.eclipse.core.runtime.IPlugin* 类型的对象强制类型转换为 org.eclipse.core.runtime.model.Plugin*Model 类型的对象的插件。尽管在 Eclipse 2.1 API 中未指定这些接口与模型类之间的关系,但是,我们明确提出了此更改,因为我们在 2.1 实现中找到了依赖于此关系的插件的实例。

描述:Eclipse API 提供了一系列接口(例如,IPluginDescriptor),通常所说的“模型”类(例如,PluginDescriptorModel)与插件和插件注册表相关。在 Eclipse 2.1 实现中,模型类实现了相关接口。在新的基于 OSGi 的运行时中,已经对插件注册表进行了重大修改,以允许插件的类装入和必备软件方面与扩展和扩展点方面分开。因此,Eclipse 3.0 运行时不能维护 2.1 中存在的实现关系。

需要的操作:依赖于这种非 API 关系的插件需要根据它们的用例修改代码。在本文档的建议更改一节以及相关类和方法的 Javadoc 中提供了有关这方面的更多信息。

27. ILibrary 实现不完整

受影响的对象:使用 org.eclipse.core.runtime.ILibrary 的插件。

描述:新的运行时采用一种与 Eclipse 不同并且不兼容的方式来维护类路径条目。因此,兼容性层不能正确地将底层的 OSGi 结构模拟为 ILibrary 对象。运行时的兼容性支持创建 ILibrary 对象,但是必须假定除了库的路径之外的任何对象的缺省值。

需要的操作:ILibrary 的用户应该考虑从适当的 Bundle(请参阅 Bundle.getHeaders())访问期望的头值(例如,Bundle-Classpath),并使用 ManifestElement helper 类来解释条目。有关更多详细信息,请参阅类 Javadoc。

28 与 URL 的格式有关的无效假定

受影响的对象:作出有关它们的安装结构、位置和本地文件系统布局的假定的插件。

描述:诸如 IPluginDescriptor.getInstallURL() 的方法将返回特定格式的 URL。尽管未指定它们的格式,但是,各种插件将根据当前实现来作出假定。例如,它们可能期望获得 file: URL,并对结果使用 URL.getFile() 和使用 java.io.File 处理。到目前为止,这已经是一种可行的方法,但是还不太完善。例如,如果插件安装在 Web 服务器上,则可能将返回 http: URL。新的 Eclipse 3.0 运行时更灵活,并为执行配置提供了更大的可能性 (例如,将整个插件维护在 JAR 中而不是分散在目录中)。即,虽然新的基于 OSGi 的运行时实际上并未废除 2.1 API,但是它揭示了当前插件中所作的许多假定都是无效的。

需要的操作:插件编写者应该确保他们需要访问的信息 是通过 getResource() 获得的(并且在类路径上),或者使用相关 API 来访问插件的内容(例如,Bundle.getEntry(String))。

29. 已移动/删除的 BootLoader 方法

受影响的对象:org.eclipse.core.boot.BootLoader 类中调用某些方法的非插件代码。

描述:已将静态方法 BootLoader.startup()、shutdown() 和 run() 移至 org.eclipse.core.runtime.adaptor.EclipseStarter(它是 OSGi 框架的一部分)。此 API 是 startup.jar 中的 main() 与 OSGi 框架/Eclipse 运行时之间的接口。重构运行时将不允许这些方法保留在 BootLoader 上。旧的 BootLoader 类现在位于运行时兼容性层(不推荐使用)并且被移动的方法不执行任何操作。

旧的 BootLoader.getRunnable() 没有任何替代对象,这是因为运行时不再能支持获取各个应用程序。然而,当用户启动平台时,他们必须指示感兴趣的应用程序。

需要的操作:通常,非常少的人使用此 API(从 Eclipse 插件中不能使用它)。当使用此 API 时,代码必须适应对 EclipseStarter 使用相应的方法。

30. 插件导出不自动包括插件的 JAR

受影响的对象:所有插件。

描述:在 Eclipse 2.1 中,插件的 build.properties 中的 bin.includes 行 不必在它们的 plugin.xml 文件中的库声明中包含 JAR 列表;可以自由添加这些 JAR。在 Eclipse 3.0 中,build.properties 的 bin.includes 一节中的文件列表是一个详尽的列表,必须包括构建或导出时插件开发者想要包括在他们的插件中的所有文件。

需要的操作:确保 build.properties 文件中的 bin.includes 行包括 plugin.xml 中列示的所有 JAR。

31. 重新导出运行时 API

受影响的对象:显示包括已更改的运行时 API 中的元素的 API 的插件。

描述:各种插件显示包括运行时 API 中的元素的 API。对 Eclipse 3.0 运行时执行了此处概述的更改之后,客户机插件必须对它们的 API 中使用的运行时 API 重新进行求值。

需要的操作:很少使用此方案,这是因为非常少的 Eclipse 运行时 API 发生更改。根据该方案,客户机可能必须更改它们的 API 或者继续依赖于兼容性层。

32. 平台上的插件解析方法

受影响的对象:使用 org.eclipse.core.runtime.Platform.parsePlugins(..., Factory) 的插件。

描述:已经移动了 org.eclipse.core.runtime.Platform.parsePlugins(..., Factory) 方法。与 Factory 自变量相关联的 API 已经从 org.eclipse.core.runtime 插件移至 org.eclipse.core.runtime.compatibility 插件(该插件取决于运行时插件)。因此,也已经移动了解析方法。

需要的操作:此方法的用户应该对 org.eclipse.core.runtime.model.PluginRegistryModel 类使用相同的方法。

33. 由段提供的插件库

受影响的对象:在它们的类路径上指定了代码但是又未提供该代码的插件 (即,JAR 是由段提供的;例如,org.eclipse.swt plug-in)。

描述:新的运行时必须在后台将 plug.xml 文件转换为 manifest.mf 文件。这是通过直接机械性转换以及对插件列示和提供的 jar 进行分析来完成的。当插件在它的类路径上指定了 jar 但是未提供该 jar 时,就没有代码供分析,并且插件转换器不能生成正确的 manifest.mf。

需要的操作: 这种插件的提供者必须进行更改以便在插件本身中提供适当的 jar,或者为它们的插件用手工生成/维护 META-INF/MANIFEST.MF 文件。通常,这可以通过使用 PDE 来获取初始清单然后在适当的 Provide-Package 头中进行添加来实现。

34. 对构建脚本的更改

受影响的对象:用来定义包含与运行时相关的 jar 和类目录的类路径的脚本(例如,Ant build.xml 文件)。

描述:新的运行时包含许多新插件和 jar。它们的简介通过运行时的重构托管到可配置的部分。对于大多数运行时情况,这些更改是透明的。但是,如果您具有定制的 build.xml(或者相似的)脚本 (该脚本当前在对 org.eclipse.core.runtime 编译代码),则将需要更新它们之后它们才能正确工作。在 <javac> 任务中包含引用 org.eclipse.core.runtime 的类路径条目的典型脚本为如下所示:

    ../org.eclipse.core.runtime/bin;../org.eclipse.core.runtime/runtime.jar

运行时插件继续包含大多数原始运行时代码。但是,只是为了保持兼容性才在运行时中提供的各种部件都包含在兼容性插件(org.eclispe.core.runtime.compatibility)中。大多数的新运行时代码都包含在插件集合(org.eclipse.osgi.*)中。

需要的操作:开发者应该根据需要添加下列条目以消除编译错误。虽然下面列示了所提供的完整的一组 jar,但是,典型用法是在编译时在类路径上只需要这组 jar 的子集。与往常一样,可以任意选择 /bin 目录中包含的内容。下面按提供插件的逻辑分组列示了这些条目:

另外,特殊情况下可能会需要下列 jar:

在更新这些脚本时,还应该寻找机会清除(即,除去)对 org.eclipse.core.boot 的引用。此插件已过时,它不再包含任何代码。这些条目可以保留在类路径上,但是它们不起任何作用,应该除去。注意除去:

    ../org.eclipse.core.boot/bin;../org.eclipse.core.boot/boot.jar

35. 对 PDE 构建 Ant 任务的更改

受影响的对象:使用 eclipse.buildScript 任务的脚本(例如,Ant build.xml 文件)。

描述:“PDE 构建”对 eclipse.buildScript 任务引入了一种新属性,用来控制插件构建脚本的生成。这是通过介绍新的基于 OSGi 的运行时来托管的。

需要的操作:如果想要使用 Eclipse 3.0 来构建基于 2.1 的产品,则在 eclipse.buildScript 中引入“buildingOSGi”属性并将它设置为 false。例如:

<eclipse.buildScript ... buildingOSGi="false"/>

36. 对 eclipse.build Ant 任务的更改

受影响的对象:使用 eclipse.buildScript 任务的脚本(例如,Ant build.xml 文件)。

描述:“PDE 构建”对 eclipse.buildScript 任务引入了一种新属性,用来控制插件构建脚本的生成。这是通过介绍新的基于 OSGi 的运行时来托管的。

需要的操作:如果想要使用 Eclipse 3.0 来构建基于 2.1 的产品,则在 eclipse.buildScript 中引入“buildingOSGi”属性并将它设置为 false。例如:

<eclipse.buildScript ... buildingOSGi="false"/>

37. 对 eclipse.fetch Ant 任务的更改

受影响的对象:使用 eclipse.buildScript 任务的脚本(例如,Ant build.xml 文件)。

描述:“PDE 构建”更改了 eclipse.fetch 任务的行为,以便以自动构建样式轻松构建 Eclipse。元素样式现在只支持一次一个条目,并且始终忽略 scriptName。

需要的操作:如果在 eclipse.fetch 调用的“elements”标记中具有条目列表,则通过几次调用 eclipse.fetch 来展开它们。如果用来设置 scriptName,则应注意,生成的访存脚本现在始终都名为“fetch_{elementId}”。例如:

<eclipse.fetch elements="plugin@org.eclipse.core.runtime, feature@org.eclipse.platform" .../>

变成

<eclipse.fetch elements="plugin@org.eclipse.core.runtime" .../>
<eclipse.fetch elements="feature@org.eclipse.platform" .../>

38. 替换 install.ini

不再包括 install.ini 文件。替代它的是配置子目录中新的 config.ini 文件。使用 install.ini 文件来指定主要功能部件(即,提供标记信息)的产品需要更改 config.ini 文件。除了新文件名之外,键名也已更改。

应该将 2.1 中 feature.default.id 键的值设置为新的 eclipse.product 键的值。应该将 eclipse.application 的值设置为“org.eclipse.ui.ide.workbench”。

最后,在 2.1 中,闪动画面的图像始终都是标记插件的目录中的 splash.bmp。而在 3.0 中,闪动画面的位置是由 config.ini 文件中的 osgi.splashPath 键显式提供的。