从 V3.0 开始,Eclipse 通过选择开放服务网关协议(Open Services Gateway Initiative,OSGi)来替换先前版本中不稳定的 Eclipse 插件技术,从而实现了一次巨大飞跃。这次转变对于用户来说几乎是透明的,因为现在所使用的插件的安装和操作看上去和以前的插件没有什么不同。
由 于 Eclipse 现在是在 OSGi 上构建的,因此我们在图 1 中看到的插件是功能完整的 OSGi 包。(图 2 显示了使用 OSGi 控制台运行 Eclipse 实例内的包。)通过使用 OSGi,Eclipse 支持业内认可的开放标准并且现在可以利用 OSGi 提供的功能,包括安全性、HTTP 服务、用户管理和其他功能。Eclipse 对 OSGi 的使用已经见到成效,因为我们看到插件间报告的冲突在减少而 Eclipse 的应用在持续增加。
OSGi Alliance 是一个独立的、非盈利性组织,负责 OSGi 技术,类似于 Eclipse Foundation 的职能。OSGi Alliance 负责制定描述 OSGi 技术的规范。简言之,OSGI 技术为应用程序开发提供了一种面向服务的基于组件的平台。各种实现都是基于这些规范的。最常见的一个实现是 Equinox,它是 Eclipse 的规范实现。OSGi 的另一个常见实现是 Apache 的 Felix 项目。
在我们继续之前,本文假定您具有 Eclipse 和 OSGi 方面的工作经验。如果不具备的话,建议先阅读 Scott Delap 的文章 “了解 Eclipse 插件如何使用 OSGi”,然后再来研究 OSGi 控制台。
这次冒险的第一步是使用 插件开发环境(Plug-in Development Environment,PDE)在 Eclipse 中创建一个简单的 OSGi 包。为此,需要使用 PDE 创建一个新的插件项目(File > New > Project > Plug-in Project)。在创建新的插件项目的过程中,确保设定正确的选项。首先,选择插件目标平台作为 OSGi Framework,具体来说就是 Equinox。最后,为了简短起见,使用 PDE 提供的 Hello OSGi Bundle 模板(参见图 3)。我们现在创建好了将在本文中使用的包。
回页首
现在我们已经有了自己的 Hello 包,可以继续并启动框架以获得 OSGi 控制台。要启动框架,我们可以利用 PDE 的 OSGi Framework 启动配置。首先,转至启动配置菜单(Run > Run ...)并为 Hello 包创建一个 OSGi Framework 启动配置(参见图 4)。此外,确保仅选择运行 Hello 包所需的必要的包。完成此操作的一种简单方法是在启动配置中按 Deselect All 键并选中 Hello 包,接下来按 Add Required Plug-ins 键。
每当走过 Eclipse 开发人员的聚集地,您总会听到人们在谈论着两个有魔力般的字眼:插件 和 包。 两者有区别么?在营销副总裁看来,两个术语是同义的。包是插件,插件就是包。我们似乎一直在交替地使用这两个术语。但是,从专业的视角来看,事情并非如 此。准确地说,Eclipse 插件是利用扩展注册表的 OSGi 包(即,包的根目录中有 plug-in.xml)。而 OSGi 包就是 OSGi 包。
完成启动配置并准备就绪之后,可以使用启动配置对话框中的 Run 按钮来启动我们的包。完成后,应当会看到类似图 5 的结果。
在图 5 中,我们看到 Hello 包已启动(使用控制台中打印的 HelloWorld 消息,表示包已被启动)并且看到osgi>提示符。OSGi 提示符类似于 DOS 或者 Bash 提示符,可以在提示符处输入对 OSGi 实例起作用的命令。在本例中,发出ss命令,该命令将快速显示所有内容的状态。建议您在普通的 Eclipse 实例中尝试此命令,将发现所有内容只不过是隐藏着的一个 OSGi 包。要获得普通 Eclipse 实例的 OSGi 控制台,只需用-console参数启动 Eclipse。
在 OSGi 动态环境中,可以轻松地启动和停止包。要测试此操作,让我们使用简单的 Hello 包。只需用stop命令即可停止包,然后用start命令启动包。您应当会看到类似图 6 的结果。
OSGi 系统的另一个强大的方面是能够在运行的 OSGi 实例中添加、删除和更新包 —— 所有操作均无需重新启动 Java™ 虚拟机。图 7 演示了包的安装和卸载。
有时在包或插件尝试启动的初始化过程中会发生错误。OSGi 控制台提供了一个有用的命令 ——diag—— 可以帮助您调试与包初始化相关的问题。例如,让我们来检验一下图 8,在尝试启动 Hello 包时,获得一个错误。为了帮助诊断错误,对包运行diag命令并将看到运行时环境中缺少一个导入包。
命令 | 描述 |
---|---|
start | 启动给定了 ID 或符号名称的包 |
stop | 停止给定了 ID 或符号名称的包 |
install | 为当前实例添加一个给定了 URL 的包 |
uninstall | 删除当前实例的具有给定 URL 的包 |
update | 为当前实例更新给定 URL 的包 |
active | 列出当前实例中所有活动的包 |
headers | 列出具有给定 ID 或符号名称的包的标头 |
ss | 列出在当前实例中注册的所有包的简短状态 |
services <filter> | 列出给定了正确过滤器的服务 |
diag | 在给定 ID 或符号名称的包上运行诊断程序 |
还有很多其他 OSGi 命令可用。这里列出的命令是我认为最有用的命令。要获得所有命令的列表,只需在控制台中键入help。
回页首
人们说 Eclipse 的绝妙之处就在于它的可扩展性。控制台是以类似方式扩展的。这是十分重要的,因为作为一名开发人员,您可能向用户提供某种服务。通过扩展控制台,您可以使高级用户或管理员能够调试关于服务的问题。
控制台不使用熟悉的扩展点,它具有一种简单的可扩展性机制。让我们通过几个示例来说明控制台的可扩展性。
使用过 UNIX® 风格的系统的人都会熟悉uname命令,该命令将打印关于运行的操作系统的名称、版本和其他信息。在 OSGi 上下文中,有各种不同风格的 UNIX 的方法就可以有 OSGi 控制台的不同实现(例如 Apache Felix、Knopflerfish 等等)。
扩展 OSGi 控制台的最重要部分是CommandProvider接口。希望扩展控制台的客户机必须实现此接口。实现此接口后,下一步是启动带有"_"的方法名称。这些方法将表示控制台中可用的命令。就这么简单!参见清单 1 中的示例。
public class Activator implements BundleActivator, CommandProvider { private BundleContext context; public void start(BundleContext context) throws Exception { this.context = context; Hashtable properties = new Hashtable(); context.registerService\ (CommandProvider.class.getName(), this, properties); } public String getHelp() { StringBuffer buffer = new StringBuffer(); buffer.append("\tuname - returns framework information\n"); return buffer.toString(); } public void stop(BundleContext context) throws Exception {} public void _uname(CommandInterpreter ci) throws Exception { String vendor = context.getProperty(Constants.FRAMEWORK_VENDOR); String version = context.getProperty(Constants.FRAMEWORK_VERSION); String osName = context.getProperty(Constants.FRAMEWORK_OS_NAME); String osVersion = context.getProperty(Constants.FRAMEWORK_OS_VERSION); System.out.println("\n " + vendor + " " + version + " (" + osName + " " + osVersion + ")"); } }
包本身可能从未质疑过自己的存在,这里提供了一个简单示例,它将打印出一个包是 vanilla 包还是 Eclipse 插件。(记住,两者都还是包!)清单 2 通过添加新方法并修改getHelp()方法来构建先前的示例。
... public String getHelp() { StringBuffer buffer = new StringBuffer(); buffer.append("\twhatami - \ returns whether the bundle is a plug-in or not\n"); buffer.append("\tuname - returns framework information\n"); return buffer.toString(); } public void _whatami(CommandInterpreter ci) throws Exception { try { long id = Long.parseLong(ci.nextArgument()); Bundle bundle = context.getBundle(id); URL url = bundle.getEntry("plugin.xml"); if(url != null) { System.out.println("\n I'm \ (" + bundle.getSymbolicName() + ") a plug-in"); } else { System.out.println("\n I'm \ (" + bundle.getSymbolicName() + ") not a plug-in"); } } catch (NumberFormatException nfe) { System.out.println("\n Error processing command"); } } ...
图 9 中显示了我们的工作结果。
回页首
本 文演示了如何使用 OSGi 控制台以及如何扩展控制台。在此过程中,我们查看了控制台以及如何扩展控制台的几个示例。您现在已经更加熟悉控制台并且知道了如何在日常的 Eclipse 开发中使用控制台。使用控制台可能甚至会让您回想起玩 Doom and Quake 时的情景。