开发者角色对HSQLDB与Eclipse工作台的集成感兴趣的开发者可以很容易地被分为两类:客户机开发者,他们只是用HSQLDB来存储数据。引擎开发者,他们通过添加新的标量函数或者存储过程来扩展HSQLDB可以识别的SQL语言。第一类开发者需要方便地访问HSQLDBJDBC驱动程序以提交SQL语句。不过,最好也可以方便地启动或停止不同的HSQLDB实例(比如,两个需要使用不同表的项目)。更高级的开发者可能还喜欢生成JavaBeans(TM),以将属性映射到表中的列,如果能生成数据访问对象(DataAccessObject),从而为查询和更新数据库中的数据提供方法,那也是很方便的。第二类开发者需要的功能包括,将新的Java类添加到数据库引擎中。他们可能还希望Eclipse调试器可以在被数据库服务调用的定制方法中设置断点和检查变量。例如,如果我希望添加一个标量函数,以返回一个字符串列的CRC32检验和,我不得不创建一个包含有publicstatic方法的类,如清单1所示,然后,当清单2中的脚本执行以后,它就可以被SQL语句所使用了。清单1.扩展HSQLDB引擎的Java类packagehsqldb.functions;importjava.util.zip.CRC32;publicclassCrcUtil{publicstaticlongcrc(Stringdata){CRC32crc32=newCRC32();crc32.update(data.getBytes());returncrc32.getValue();}}清单2.添加新标量函数到HSQLDB引擎的SQL脚本文件CREATEALIASCRCFORhsqldb.functions.CrcUtil.crc;GRANTALLONCLASShsqldb.functions.CrcUtilTOPUBLIC;客户机开发者所期望的大部分特性不在本系列文章的范围之内。有很多SQL监控器、OO-关系映射工具和其他数据库实用工具都可以作为Eclipse插件得到,它们独立于数据库,可以与我们的HSQLDB插件共同为此类开发者提供一个完整的环境。本系列将着眼于数据库引擎开发者所关心的特性。HSQLDB插件,第二版本系列的第2部分最初计划要创建一个专门的HSQLDB视图,在这里可以编辑很多配置(服务器端口、用户、密码和数据库文件路径),并且它们每一个都可以独立地启动或停止。但我意识到我只需要让HSQLDB作为一个标准的Java应用程序来运行,EclipseJDT本身就已经具备大部分的这些特性,于是我从根本上改变了这个计划。本文现在的计划是定义一类专用的Java项目,在这些项目里HSQLDB库将自动可用,它们的行为依赖于服务器和相关工具(数据库管理器和脚本工具)的启动。当然,应该基于每个项目存储HSQLDB连接参数,而不是在整个工作台中只保存一次。项目的性质和行为Eclipse用项目性质来定义一类新项目,项目性质是平台中可用的众多扩展点之一。每一个项目可以有多个性质,所以不需要创建全新的项目类,只需复制或者继承Java项目类的功能。您可以只告诉工作台,新性质依赖于JDT已定义的Java项目性质。Java性质提供了编辑Java类、创建单元测试用例和调试Java应用程序的所有工具。HSQLDB引擎性质提供了启动、停止和配置HSQLDB的方法。清单3显示了plugin.xml文件定义新性质的代码片断。它与一个类相关联,这个类必须实现IProjectNature,并可以将生成器和其他元素添加到工作台,但是这个第二版的HSQLDB插件不需要去做任何事情。总之,必须给出性质实现类,不然工作台不会将性质添加到项目中。使用新性质很简单,我们只需要将特定的项目设定为HSQLDB行为可用(或者不可用)。清单3.plugin.xml清单文件中定义HSQLDB引擎项目性质的片断extensionid=hsqldbEnginename=HSQLDBEnginepoint=org.eclipse.core.resources.naturesrequires-natureid=org.eclipse.jdt.core.javanature/requires-natureruntimerunclass=hsqldb.nature.DBEngineNature/run/runtime/extension每一个Java项目将获得一个HSQLDB菜单。它被初始化时只包含有一个选项,即“AddHSQLDBEnginenature”,见图1。如果您曾经尝试过使用EclipseConsortium的EMF插件,您将发现两者在概念上是相同的。图1.Java项目上下文菜单中的HSQLDB子菜单当用户选择了这一动作,菜单将发生变化并显示出更多选项,包括启动和停止HSQLDB,以及以独立模式(进行中)或者以客户机/服务器模式启动数据库管理器,见图2。我们在第一版插件中定义的,在工作台顶部菜单栏上的“HSQLDB”菜单将消失,由每个Java项目上下文菜单中的“HSQLDB”子菜单所取代。图2.添加引擎性质后的HSQLDB子菜单操作的可见与启用在第一版HSQLDB插件中,每一步操作都要去检查它是否可以执行(例如,不允许启动数据库服务器的两个实例)。我已经注意到了Eclipse没有提供在程序中设置菜单项状态的简单方法,因为工作台试图去自己管理所有事情,只有当真正要调用插件代码时才加载插件。既然每一步操作都依赖于工作台资源(一个Java项目),那么工作台可以确定每一个选项什么时候应该可见或者被启用,而不必调用插件。元素visibility和enablement可以有子元素,比如objectState,该子元素查询资源属性以设置每一个操作的状态。清单4显示了plugin.xml中定义5个objectContribution的片断:“RunHSQLDBSQLScript”操作,具备此新性质的项目中的任何*.sql文件都可见。“HSQLDB”子菜单包含两组选项,对任何Java项目都可见。如果两组都有关联到它们的操作,会画出一条分隔线将它们分开。只有当Java项目具有我们新定义的性质时,所有在本系列第1部分最初定义的HSQLDB操作才是可见的,例如启动和停止服务器。当Java项目没有插件自己定义的性质时“AddHSQLDBEnginenature”是可见的。最后,当Java项目具有我们的新性质时,“RemoveHSQLDBEnginenature”可见。清单4.plugin.xml清单文件中定义HSQLDB菜单操作的片断extensionpoint=org.eclipse.ui.popupMenusobjectContributionobjectClass=org.eclipse.core.resources.IFilenameFilter=*.sqlid=hsqldb.ui.SQLScriptFilesvisibilityobjectStatename=projectNaturevalue=hsqldb.ui.hsqldbEngine/objectState/visibilityactionlabel=RunHSQLDBScriptclass=hsqldb.ui.popup.actions.HsqldbRunScriptmenubarPath=additionsenablesFor=1id=hsqldb.ui.HsqldbRunScriptenablementobjectStatename=projectSessionPropertyvalue=hsqldb.ui.running/objectState/enablement/action/objectContributionobjectContributionobjectClass=org.eclipse.jdt.core.IJavaProjectid=hsqldb.ui.HsqldbEngineMenumenulabel=HSQLDBpath=additionsid=hsqldb.ui.HsqldbProjectseparatorname=hsqldb.ui.group1/separatorseparatorname=hsqldb.ui.group2/separator/menu/objectContributionobjectContributionobjectClass=org.eclipse.jdt.core.IJavaProjectid=hsqldb.ui.HsqldbEngineActionsvisibilityobjectStatename=naturevalue=hsqldb.ui.hsqldbEngine/objectState/visibilityactionlabel=RunDatabaseManager(Standalone)icon=icons/dbmansa.gifclass=hsqldb.ui.popup.actions.RunDatabaseManagerStandalonemenubarPath=hsqldb.ui.HsqldbProject/group1enablesFor=1id=hsqldb.ui.RunDatabaseManagerStandaloneenablementnotobjectStatename=sessionPropertyvalue=hsqldb.ui.running/objectState/not/enablement/actionactionlabel=RunDatabaseManager(Client)icon=icons/dbman.gifclass=hsqldb.ui.popup.actions.RunDatabaseManagermenubarPath=hsqldb.ui.HsqldbProject/group1enablesFor=1id=hsqldb.ui.RunDatabaseManagerenablementobjectStatename=sessionPropertyvalue=hsqldb.ui.running/objectState/enablement/actionactionlabel=StopHSQLDBServericon=icons/stop.gifclass=hsqldb.ui.popup.actions.StopHsqldbServermenubarPath=hsqldb.ui.HsqldbProject/group1enablesFor=1id=hsqldb.ui.StopHsqldbServerenablementobjectStatename=sessionPropertyvalue=hsqldb.ui.running/objectState/enablement/actionactionlabel=StartHSQLDBServericon=icons/start.gifclass=hsqldb.ui.popup.actions.StartHsqldbServermenubarPath=hsqldb.ui.HsqldbProject/group1enablesFor=1id=hsqldb.ui.StartHsqldbServerenablementnotobjectStatename=sessionPropertyvalue=hsqldb.ui.running/objectState/not/enablement/action/ob