国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
[轉]Eclipse 和 HSQLDB: 將關系數(shù)據(jù)庫服務器嵌入到 Eclipse 中(1) - myali88的專欄
本文介紹如何開發(fā)將 HSQLDB 純 Java 關系數(shù)據(jù)庫服務器集成到 Eclipse Workbench 中的插件。盡管不如 DB2 功能強大,也不如 MySQL 流行,但 HSQLDB(超音速 SQL 數(shù)據(jù)庫)可以滿足很大范圍內 Java 應用程序的需要,因為它具有可擴展性,而且對內存/處理器的要求不高。

超音速 SQL 數(shù)據(jù)庫后來正式更名為 HSQLDB,它是一類純 Java 撰寫的嵌入式關系數(shù)據(jù)庫服務器,您可以在單機模式(使用直接文件訪問)或客戶機/服務器模式中使用它,它支持大量的并發(fā)用戶。盡管不如 DB2 功能強大,也不如 MySQL 流行,但 HSQLDB(超音速SQL數(shù)據(jù)庫)可以滿足很大范圍內 Java 應用程序的需要,因為它具有可擴展性,而且對內存/處理器的要求不高。

HSQLDB 是一類使用方便的 Java 開發(fā)數(shù)據(jù)庫,因為它支持 Structured Query Language(SQL)的豐富子集,并且 Java 程序員根本不需要在他們的開發(fā)工作站上安裝嚴重消耗處理器、內存和磁盤空間的數(shù)據(jù)庫服務器。它對于集成到 Eclipse IDE 中來說是一種很理想的工具,既能為新手也能為經驗豐富的開發(fā)人員提供有用的工具。

本文及同一系列的后續(xù)文章將向您展示如何構建一組 Eclipse 插件,以將 HSQLDB 嵌入到 Eclipse Workbench 中。您將看到一個現(xiàn)實世界中的例子,目的是說明如何在考慮到 API 和用戶接口(UI)的情況下開發(fā)這類插件,以及如何評估可供選擇的方法以給用戶帶來所需要的功能。本文假定您使用的是 Eclipse SDK 分布,而不是 Platform Runtime-Binary 加上 JDT。但如果只是為了開發(fā)常規(guī) Java 應用程序,則后者更加適合。

在這個系列中,我們將根據(jù)“Levels of Integration” 一文中描述的基本原理(請參閱本文后面的 參考資料 中給出的鏈接),使用三個步驟創(chuàng)建并擴展插件組:

  1. 運行 Eclipse 中現(xiàn)有的工具, 以便從 Workbench 菜單容易地訪問所需要的預先存在的工具。
  2. 探討如何使用 Eclipse 的其他功能來向預先存在的工具集添加值,從而提高 Java 開發(fā)人員的生產力。
  3. 使用 SWT 來重寫工具,以實現(xiàn)與 Eclipse Workbench 的無縫集成。

了解 HSQLDB
您可以從 SourceForge(hsqldb.sourceforge.net; 請參閱 參考資料 中給出的鏈接)下載 HSQLDB,其中包括源代碼和文檔。這里注意不要與已經被凍結的原始 SourceForge 項目( hsql.sourceforge.net )相混淆。

二進制分布是一個標準的 ZIP 文件,而您要做的就是把這個 ZIP 文件解壓縮到您硬盤上的某個地方。所有 HSQLDB 組件 ——數(shù)據(jù)庫引擎、服務器進程、JDBC 驅動程序、文檔以及一些實用工具——都放在一個單獨的 JAR 包中,這個包安裝在 lib/hsqldb.jar 中,大小在 260 KB 左右。運行數(shù)據(jù)庫引擎只需 170 KB 的 RAM,這即使是 PDA (如 Sharp 生產的 Zaurus)也能夠滿足,而且包括源文件和文檔在內的整個下載文件小到可以放到一張標準的 1.44 MB 軟盤上。

您可以從命令行啟動數(shù)據(jù)庫服務器和實用工具,具體方法是調用像 org.hsqldb.Server 和 org.hsqldb.util.DatabaseManager 這樣的方便的類,這兩個類均可以接受為數(shù)不多的一組命令行選項,如“-url”(用于遠程連接)、“-database”(用于直接文件訪問)和“-user”。還有一種“-?”選項也可以被接受,其作用是提供關于有效命令行語法的幫助。

造成 HSQLDB 簡單性的關鍵因素是SQL語句執(zhí)行的順序化。也就是說,盡管許多并發(fā)用戶可以連接到數(shù)據(jù)庫上(當數(shù)據(jù)庫以服務器模式運行時),但是所有 SQL 語句都被放到一個隊列中,然后一次執(zhí)行一條。因此不需要實現(xiàn)復雜的鎖定及同步算法。盡管如此,HSQLB 還是實現(xiàn)了 ACID(Atomicity, Consistency, Isolation, and Durability,即原子性、一致性、隔離性和持久性) 語義。換句話說,它是一個事務性的數(shù)據(jù)庫,但僅僅處于讀未提交級別,還不具備事務隔離功能。HSQLDB 實際上是為嵌入式應用程序而不是為共同數(shù)據(jù)中心而創(chuàng)建的。

如果您想要使用觸發(fā)器、聚合函數(shù)、外部聯(lián)接、視圖以及其他 SQL 功能,HSQLB 都可以滿足您的需要(大部分輕量級關系數(shù)據(jù)庫無法做到這一點)。通過把您的 Java 類添加到 HSQLB 的類路徑中,您可以實現(xiàn)存儲過程。然后您發(fā)出一條 CREATE FUNCTION 語句即可大功告成。事實上,像 SQRT 和 ABS 之類的許多標準 SQL 函數(shù)都被實現(xiàn)為到標準 Java 類(比如 java.lang.Math)的直接映射 。

HSQLDB 的運行模式
HSQLDB 引擎可以以多種模式運行,以適應不同的應用場合:

駐留內存模式
所有數(shù)據(jù)庫表和索引都放在內存中,而且永遠不會保存到磁盤上。在您發(fā)出為什么有人想要使用在應用程序終止時就會丟失的數(shù)據(jù)庫這樣的疑問之前,請先考慮為您可以使用標準 SQL 語句進行查詢、排序、分組和更新的數(shù)據(jù)庫數(shù)據(jù)擁有一塊本地高速緩存。

單機模式
應用程序使用 JDBC 創(chuàng)建一個數(shù)據(jù)庫連接,并且 HSQLDB 引擎運行在該應用程序中,這時允許直接訪問數(shù)據(jù)庫文件。不能存在并發(fā)用戶(應用程序獨占地訪問數(shù)據(jù)庫文件),但因此也沒有額外的線程和 TCP 連接開銷。單機模式是許多嵌入式應用程序的首選模式。

服務器模式
這是類似于其他關系數(shù)據(jù)庫的標準客戶機/服務器數(shù)據(jù)庫配置,允許出現(xiàn)使用 TCP 套接字的并發(fā)連接。大部分開發(fā)人員喜歡這種模式,因為它允許任何 JDBC 客戶機在主應用程序仍在運行的情況下連接并查詢/更新表。

Web服務器模式
HSQLDB 可以用作 Web 服務器,可以通過 HTTP 接受 SQL 查詢;也能作為任何標準 Web 容器中的 servlet 來運行,可以穿過防火墻或者安裝在 Web 宿主服務上,而不用涉及到提供者支持小組(和昂貴的數(shù)據(jù)庫宿主選項)。由于 HTTP 是無狀態(tài)的,所以本模式中不存在事務。

HSQLDB 數(shù)據(jù)庫文件結構
HSQLDB 將所有表和索引數(shù)據(jù)放在內存中, 將所有發(fā)出的 SQL 語句保存到一個名為 database.script 的文件中,該文件同時也充當著事務日志的角色。初始化引擎之后,該文件被讀取,然后其中所有的 SQL 語句都被運行,從而完成整個數(shù)據(jù)庫的重建。停機期間,HSQLDB 引擎將生成一個新的 database.script 文件,其中只包含最少的語句,目的是讓數(shù)據(jù)庫可以快速啟動。

除了默認放在內存中的表之外,HSQLDB 還支持“緩存”表和“文本”表。所有緩存表的數(shù)據(jù)放在一個名為 database.data 的文件中,而文本表的數(shù)據(jù)則放在由 set table source 非標準 SQL 語句命名的任意分隔文本文件(像 CSV 文件)中。緩存表支持比可用 RAM 大的數(shù)據(jù)集,而文本表則可以作為一種導入導出數(shù)據(jù)的方便手段。

除了 database.script 和 database.data 文件之外,任何 HSQLDB 數(shù)據(jù)庫還可能包含一個 database.properties 文件,管理員可以在該文件中設置許多影響到 ANSI SQL 兼容性的參數(shù)。所有數(shù)據(jù)庫文件(文本表數(shù)據(jù)文件除外)必須放在同一個目錄中。

不存在創(chuàng)建 HSQLDB 數(shù)據(jù)庫的顯式方法。如果您要求引擎打開一個目前不存在的數(shù)據(jù)庫文件(使用服務器模式的 -database 選項或單機模式的 JDBC URL),就會創(chuàng)建該文件及其所在目錄。所以,如果您肯定那個空數(shù)據(jù)庫中存在數(shù)據(jù),請檢查是否有錄入錯誤。

現(xiàn)在讓我們開始開發(fā)插件!

創(chuàng)建 HSQLDB Eclipse 插件組
把現(xiàn)有的應用程序放到 Eclipse 這樣功能強大的工具中去并不是一件容易的事情。值得慶幸的是,HSQLDB 和 Eclipse 均降低了上述任務的難度,因為 HSQLDB 本身可以嵌入到其他應用程序中,而 Eclipse 提供了清晰而且易于理解的插件基礎設施以及用于創(chuàng)建新插件的健壯的開發(fā)環(huán)境 PDE。即使您以前從未接觸過 Eclipse 插件開發(fā),PDE 也可以讓您很容易上手。請參閱本文后面 參考資料 部分中講述 Eclipse 基礎知識的文章。

這些指導性內容假定您使用的是 Eclipse SDK 分布,而不是 Platform Runtime-Binary 加 JDT。但如果您只是要開發(fā)常規(guī) Java 應用程序,則后者更加適合。您可以使用您最喜歡的操作系統(tǒng),因為我們將只使用 Java 代碼,而根本不會用到本機代碼。

為了創(chuàng)建有用的插件組并盡可能地少書寫代碼,我們將從最不費力的工作開始。稍后,在這個系列的下一部分內容中,我們將看到如何利用 Eclipse 功能為 HSQLDB 提供增值。

在本文中,我們將集中講述我們代碼的下列功能:

  1. 以服務器模式啟動 HSQLDB 引擎,這樣用戶應用程序和 SQL 控制臺(像 HSQLDB 自帶的 DatabaseManager 實用工具)都可以運行 SQL 語句。
  2. 完全停止 HSQLDB 服務器。
  3. 調用 DatabaseManager 實用工具,這樣開發(fā)人員可以從 Workbench 交互式地輸入 SQL 語句。
  4. 使用 HSQLDB ScriptTool 實用工具運行 SQL 腳本文件。這些年來,為了創(chuàng)建數(shù)據(jù)庫表和插入測試數(shù)據(jù),我已經在我的項目文件夾中放入了大量 *.sql 文件,而且長久以來,我一直希望能夠有一種容易的方式來運行它們。
  5. 配置 HSQLDB 連接屬性,比如 TCP 端口和管理員密碼。

如何才能使得這些函數(shù)可以為 Workbench 所用呢?完成前面三步最容易的方式是提供一個 actionSet,它被添加到新的頂級菜單中并且可從它自己的工具欄訪問。運行 SQL 腳本文件的操作必須只被綁定到擴展名為“*.sql” 的文件上,所以這將是一個 objectContribution, 它被 Workbench 添加到顯示這些文件的任意視圖上的彈出式菜單中。最后,連接參數(shù)要能很好地符合插件的參數(shù)選擇頁面,從 Workbench Window 菜單中可以訪問這個頁面。

圖 1 顯示了新的菜單和工具欄,而圖 2 顯示了 Navigator 視圖的彈出式菜單中的新項,圖 3 則顯示了屬性頁面,這樣您就可以看到我們的插件組的第一個版本是什么樣子。

圖 1.HSQLDB 菜單和相關工具欄

圖 2. 添加到 *.sql 文件的彈出式菜單項

圖 3. HSQLDB 連接屬性

把 HSQLDB 變成一個 Eclipse 插件
構建我們的插件組的第一步是把 HSQLDB 本身包裝成一個 Eclipse 插件。這個插件將只包含 hsqldb.jar 和 Workbench 要求的必要的plugin.xml 文件。如果您已經瀏覽了標準 Eclipse 插件目錄,那么您可能已經發(fā)現(xiàn),JUnit, Xerces, Tomcat,以及其他常見的 Java 包被隔離在它們各自的插件中,未曾改變,而且所有的 Eclipse 細節(jié)都被封裝在其他插件中。這種劃分方式使得這些第三方工具易于更新,而不一定要求改變 Eclipse 本身。另外一個好處就是與許多插件共享這些常見的庫很容易。

打開您的 Eclipse SDK 安裝,并創(chuàng)建一個新的插件項目;將其命名為 hsqldb.core(我知道推薦使用的名稱是 org.hsqldb.core,但是我不愿意假裝使用了 HSQLDB 名稱空間?;蛟S HSQLDB 開發(fā)人員閱讀至此會贊同這個想法,并推薦它為“正式的”Eclipse 集成插件;這樣的話該名稱極有可能被改掉)。確保選中的是“Empty Plugin” 選項, 而不是任何插件模板;否則,您將得到一個毫無用處的頂級插件類,如果您創(chuàng)建了該類之后希望刪掉它,那么它可以被安全地刪除。把 hsqldb.jar 從您的 HSQLDB 安裝拷貝到項目目錄中,并將其添加到項目的 Runtime。您可以使用 PDE Plugin Manifest Editor或者簡單地拷貝清單 1 中的內容來完成這項工作。

清單 1. 用于 hsqldb.core 插件的 plugin.xml 清單文件
<?xml version="1.0" encoding="UTF-8"?><plugin   id="hsqldb.core"   name="Hsqldb Core Plug-in"   version="0.0.1"   provider-name="Fernando Lozano (www.lozano.eti.br)">   <runtime>      <library name="hsqldb.jar">         <export name="*"/>      </library>   </runtime></plugin>

添加 Workbench 擴展
接下來,創(chuàng)建名為 hsqldb.ui 的第二個插件項目。這個項目將為插件組的第一修訂本包含所有的 Eclipse 擴展:包含三個操作的一個操作集、與 *.sql 文件相關的對象作用,以及一個屬性頁面。將其主類(Plugin 類)命名為 PluginUi,并接受包的默認名稱 hsqldb.ui。

使用 Plugin Manifest Editor 打開 plugin.xml 文件,并選擇 Extensions 選項卡。將所分配菜單更名為 HSQLDB 并改變示范操作,使其顯示標簽“Runs HSQLDB Database Manager”。向帶有標簽“Stops HSQLDB database server” 和“Starts HSQLDB database server”的同一個 actionSet 添加另外兩個操作,并為每個操作提供惟一的操作 ID 和實現(xiàn)類。請注意,上述操作將以與創(chuàng)建時相反的順序(即與在插件清單文件中出現(xiàn)的順序相反)顯示在菜單和工具欄中。

單擊 Add 按鈕,從而使用 Extension 模板、彈出式菜單和屬性頁面添加兩個新的擴展。彈出式菜單應該與 *.sql 文件模式相關聯(lián),但是屬性頁面字段應該通過編程進行設置。

圖 4 顯示了 Plugin Manifest 編輯器的最終外觀,并顯示了所有的插件擴展;圖 5 顯示了對象分配的屬性(注意針對 *.sql 文件的過濾器),而圖 6 顯示了文件資源彈出式菜單中的“Run SQL Script”操作的屬性。 圖標在本文的源代碼中給出(請參閱 參考資料),但是我敢肯定您認識有比這畫得更好的圖形專家!

圖 4. 清單編輯器上的 HSQLDB 操作

圖 5. 清單編輯器上的 HSQLDB 對象分配

圖 6. 清單編輯器上的 Run SQL Script 操作

在能夠給我們的操作添加代碼之前,我們需要將這種 UI 插件與相應的核心插件區(qū)別開來,否則它將不能訪問 HSQLDB 類。轉到 Plugin Manifest Editor 上的“Dependencies” 頁面,并添加一個插件依賴性,如圖 7 所示。某些依賴性,像“eclipse.ui”,由 PDE 自動進行配置,而其他依賴性,像 “org.eclipse.debug.core”,則在對操作進行編碼時添加。如果您情愿直接編輯 XML 代碼,清單 2 顯示了 hsqldb.ui 插件的完整 plugin.xml 文件。

要完成插件的安裝工作,請?zhí)砑右粋€新類到 hsqldb.ui 包中,然后將其命名為 HsqldbUtil。這個類將包含所有直接處理 HSQLDB 的代碼,并使分配的擴展代碼保持簡單。

圖 7. hsqldb.ui 插件依賴性

清單 2. hsqldb.ui 插件的 plugin.xml 清單文件
<?xml version="1.0" encoding="UTF-8"?><plugin   id="hsqldb.ui"   name="Hsqldb Ui Plug-in"   version="0.0.1"   provider-name="Fernando Lozano (www.lozano.eti.br)"   class="hsqldb.ui.PluginUi">   <runtime>      <library name="ui.jar"/>   </runtime>   <requires>      <import plugin="org.eclipse.core.resources"/>      <import plugin="org.eclipse.ui"/>      <import plugin="hsqldb.core"/>      <import plugin="org.eclipse.debug.core"/>      <import plugin="org.eclipse.jdt.launching"/>      <import plugin="org.eclipse.debug.ui"/>   </requires>   <extension         point="org.eclipse.ui.actionSets">      <actionSet            label="Hsqldb"            visible="true"            id="hsqldb.ui.actionSet">         <menu               label="Hsql&db"               id="hsqldbMenu">            <separator                  name="dbServerGroup">            </separator>         </menu>         <action               label="Run Hsql &Database Manager"               icon="icons/dbman.gif"               tooltip="Runs the Hsql database manager"               class="hsqldb.ui.actions.HsqldbDatabaseManagerAction"               menubarPath="hsqldbMenu/dbServerGroup"               toolbarPath="dbServerGroup"               id="hsqldb.ui.actions.HsqldbDatabaseManagerAction">            <enablement>               <pluginState                     value="activated"                     id="hsqldb.ui">               </pluginState>            </enablement>         </action>         <action               label="S&top Hsqldb"               icon="icons/stop.gif"               tooltip="Stops the Hsql database server"               class="hsqldb.ui.actions.HsqldbStopAction"               menubarPath="hsqldbMenu/dbServerGroup"               toolbarPath="dbServerGroup"               id="hsqldb.ui.actions.HsqldbStopAction">            <enablement>               <pluginState                     value="activated"                     id="hsqldb.ui">               </pluginState>            </enablement>         </action>         <action               label="&Start Hsqldb"               icon="icons/start.gif"               tooltip="Starts the Hsql database server"               class="hsqldb.ui.actions.HsqldbStartAction"               menubarPath="hsqldbMenu/dbServerGroup"               toolbarPath="dbServerGroup"               id="hsqldb.ui.actions.HsqldbStartAction">            <enablement>               <pluginState                     value="installed"                     id="hsqldb.ui">               </pluginState>            </enablement>         </action>      </actionSet>   </extension>   <extension         point="org.eclipse.ui.perspectiveExtensions">      <perspectiveExtension            targetID="org.eclipse.ui.resourcePerspective">         <actionSet               id="hsqldb.ui.actionSet">         </actionSet>      </perspectiveExtension>   </extension>   <extension         point="org.eclipse.ui.popupMenus">      <objectContribution            objectClass="org.eclipse.core.resources.IFile"            nameFilter="*.sql"            id="hsqldb.ui.SQLScriptFiles">         <action               label="Run SQL Script"               class="hsqldb.ui.popup.actions.HsqldbRunScript"               menubarPath="additions"               enablesFor="1"               id="hsqldb.ui.HsqldbRunScript">            <enablement>               <pluginState                     value="activated"                     id="hsqldb.ui">               </pluginState>            </enablement>         </action>      </objectContribution>   </extension>   <extension         id="hsqldb.ui.preferences"         point="org.eclipse.ui.preferencePages">      <page            name="HSQLDB Server"            class="hsqldb.ui.preferences.HSQLDBPreferencePage"            id="hsqldb.ui.preferences.HSQLDBPreferencePage">      </page>   </extension></plugin>

啟動 HSQLDB
使用類 org.hsqldb.Server 以服務器模式啟動 HSQLDB 引擎相當容易。以HSQLDB 數(shù)據(jù)庫名稱(路徑+數(shù)據(jù)庫文件的基本名稱)、用于監(jiān)聽連接請求的TCP 端口以及一個用于判別停機時它是否應該調用 System.exit() 的標志作為命令行參數(shù)。下面的命令行是運行 HSQLDB 時的典型情況

java -cp /opt/hsqldb/hsqldb.jar org.hsqldb.Server -database /tmp/bd -port 9001 -system_exit=true

上面這一行命令創(chuàng)建了 /tmp/db.script、 /tmp/db.properties 和 /tmp/db.data 三個數(shù)據(jù)庫文件。

我們可以使用 Server 類主方法并傳遞一個字符串數(shù)組作為其參數(shù)。但是我們必須在一個新線程中做這項工作;否則,我們將鎖定整個 Workbench。惟一的插件類維持一個到這個線程的引用,這樣它就能夠在連接到某臺服務器之前檢查該服務器是否已經啟動,并且還可以檢查它是否正在運行,因為任何客戶機均可連接到這臺服務器上,然后提交 SHUTDOWN 語句終止它的運行。

清單 3 中的代碼顯示了 hsqldb.ui.actions.HsqldbStartAction 的 run 方法,而清單 4 顯示了 hsqldb.ui.HsqldbUtil startHsqldb 的代碼,這些代碼實際上啟動了服務器。稍后我們將討論管理用戶反饋的技術。

上述代碼最有趣的部分是我們如何找到一個位置來放置數(shù)據(jù)庫文件。一個名為 .hsqldb 的項目如果不存在就會被創(chuàng)建,而在該項目中引擎將查找 database.script 和其他數(shù)據(jù)庫文件。

Eclipse 在一個可以保存任何配置文件的標準目錄中提供了所有插件??梢酝ㄟ^調用 plugin.getStateLocation 來得到這樣一個目錄,但是我并不覺得數(shù)據(jù)庫文件實際上是插件配置文件。它們看起來更像是用戶數(shù)據(jù)文件,而且照此說來,它們應該位于開發(fā)人員工作區(qū)中的項目內。

清單 3. 以服務器模式啟動 HSQLDB 的操作,來自 hsqldb.ui.actions.HsqldbStartAction
    public void run(IAction action) {        // check a database was really started by the plug-in        PluginUi plugin = PluginUi.getDefault();        if (plugin.getHsqldbServer() != null) {            ((ApplicationWindow)window).setStatus(                "HSQLDB Server already running.");        }        else {            Cursor waitCursor = new Cursor(window.getShell().getDisplay(),                SWT.CURSOR_WAIT);            window.getShell().setCursor(waitCursor);            try {                HsqldbUtil.startHsqldb();                ((ApplicationWindow)window).setStatus("HSQLDB Server started.");            }            catch (CoreException e) {                MessageDialog.openError(window.getShell(),                    "Hsqldb Plugin",                    "Could not create HSQLDB database project.");                e.printStackTrace(System.err);            }            finally {                window.getShell().setCursor(null);                waitCursor.dispose();            }        }    }            


清單 4. 真正以服務器模式啟動 HSQLDB 的代碼,來自 hsqldb.ui.HsqldbUtil
    public static void startHsqldb() throws CoreException {        PluginUi plugin = PluginUi.getDefault();        // finds project local path for database files        IWorkspaceRoot root = PluginUi.getWorkspace().getRoot();        IProject hsqldbProject = root.getProject(".hsqldb");        if (!hsqldbProject.exists()) {            hsqldbProject.create(null);        }        hsqldbProject.open(null);        IPath dbPath = hsqldbProject.getLocation();        final String database = dbPath.toString() + "/database";        // starts a new thread to run the database server        final HsqldbParams params = getConnectionParams();        Thread server = new Thread() {            public void run() {                String[] args = { "-database", database,                    "-port", String.valueOf(params.port),                    "-no_system_exit", "true" };                Server.main(args);            }        };        plugin.setHsqldbServer(server);        server.start();    }            

停止 HSQLDB
要停止 HSQLDB 服務器,所需要的只是一個作為 SQL 語句的 SHUTDOWN 命令。如清單 5 所示,來自 hsqldb.ui.HsqldbUtil 的 stopHsqldb 方法完成了這個任務。相應操作對應的代碼和啟動服務器時描述的代碼幾乎完全相同,所以這里沒有列出。清單 5 中拋出了 ClassNotFoundException (來自 Class.forName)和 SQLException 異常,所以操作代碼能夠提供足夠的反饋給用戶。

清單 5. 用于停止 HSQLDB 服務器的代碼
    public static void stopHsqldb() throws ClassNotFoundException,                SQLException {        PluginUi plugin = PluginUi.getDefault();        HsqldbParams params = getConnectionParams();        // submits the SHUTDOWN statement        Class.forName("org.hsqldb.jdbcDriver");        String url = "jdbc:hsqldb:hsql://127.0.0.1:" + params.port;        Connection con = DriverManager.getConnection(url, params.user,            params.passwd);        String sql = "SHUTDOWN";        Statement stmt = con.createStatement();        stmt.executeUpdate(sql);        stmt.close();        // no need to close a dead connection!        plugin.setHsqldbServer(null);    }            

運行 HSQL Database Manager
運行 HSQLDB 中的 Database Manager 實用工具比運行服務器本身還要棘手一點。因為服務器被創(chuàng)建為可以嵌入到其他應用程序中,而上述實用工具則計劃作為單機應用程序或 Java applet 來運行。盡管兩種模式均接受命令行參數(shù)(或 applet 參數(shù)),我們還是不希望僅僅為了得到一個用戶可以在其中輸入 SQL 語句的窗口,就需要額外增加啟動一個新的 Java VM 的開銷。直接調用類 static void main(String[] args) 不會如預期一樣工作,因為它將調用 System.exit() 終止 Workbench。

瀏覽 org.hsqldb.util.DatabaseManager 源代碼之后,我們發(fā)現(xiàn)實例化和初始化一個 JDBC 連接很容易,但是所必需的方法不是公共的。所以我們可以在 HSQLDB 源樹中創(chuàng)建一個名為 org.hsqldb.util.PatchedDatabaseManager 的類,然后使用所提供的 Ant 構建腳本生成一個新的 hsqldb.jar,其中包含我們打過補丁的 Database Manager。只有兩個方法的可見性需要改為 public:void main() 和 void connect(Connection con)。清單 6 顯示了插件如何使用這兩個方法運行補丁類。

Database Manager 是一個 AWT 應用程序 (參見圖 8), 它將創(chuàng)建自己的事件線程(獨立于 Eclipse SWT 線程),并且在調用 System.exit() 關閉 Workbench 之后就會終止??梢赃\行該實用程序的多個實例而不會導致問題,除非沒有 Workbench 窗口可以依靠。對于我們的 HSQLDB 插件的第一修訂本來說,這很好,但是在這個系列結束之前,我們必須將其改為一個 SWT 應用程序,就像 Eclipse 視圖那樣嵌入其中。

圖 8. HSQLDB Database Manager

清單 6. 啟動打過補丁的 Database Manager 實用程序
    public static void runDatabaseManager() throws ClassNotFoundException,                SQLException {        PluginUi plugin = PluginUi.getDefault();        HsqldbParams params = getConnectionParams();        // creates a connection to the internal database         String url = "jdbc:hsqldb:hsql://127.0.0.1:" + params.port;        Class.forName("org.hsqldb.jdbcDriver");        Connection con = DriverManager.getConnection(url, params.user,            params.passwd);        if (con != null) {            // needed to patch DatabaseManager so it could            // be initialized and use the supplied connection             PatchedDatabaseManager dm = new PatchedDatabaseManager();            dm.main();            dm.connect(con);        }            }            

運行 SQL 腳本
HSQLDB Script Tool 讀取純文本文件,并依靠一個給定的 JDBC URL 執(zhí)行文件中包含的 SQL 語句。SQL 語句批處理由 go 命令進行分隔, 而且腳本也可以使用 print 命令在腳本中書寫消息。

熟悉其他數(shù)據(jù)庫系統(tǒng)的開發(fā)人員創(chuàng)建的腳本可能僅僅包含由分號(;)分隔開的 SQL 語句,但是這使得 HSQLDB 可以在單個批處理中運行所有腳本,而只返回最后一條語句的結果。您需要在 SQL 語句之間包含 go 命令,以接受每一條語句的結果。

讓用戶瀏覽腳本結果最容易的方法是把它們放入一個控制臺視圖中,就像從 Workbench 調用的 Java 應用程序和 Ant 構建腳本一樣。這要求創(chuàng)建一個 Java Launch 配置,而該配置又會創(chuàng)建另一個 Java VM。因為 SQL 腳本存在時間較短,所以我們可以認為其開銷是可以接受的,而且如果您認為 Database Manager 也應該在它自己的 VM 中被調用,您可以使用清單 7中給出的 runScriptTool 方法作為一個例子。

清單 7 是本文(這個系列的第一篇)中最長的清單,其中大部分內容是關于建立一個包含正確的 JRE 自舉類(必須被顯式設定)和 hsqldb.core 插件中的 hsqldb.jar 的類路徑。查閱本文末尾的 參考資料 部分可以獲得更多關于運行由 Eclipse 提供的框架以及由 JDT 提供的擴展的信息。

對于熟悉其他 GUI 工具包的開發(fā)人員來說,如何獲取被選中 SQL 腳本文件的路徑并不是一件顯而易見的事情。IObjectActionDelegate 接口由擴展資源彈出式菜單的對象分配實現(xiàn),調用它的 run 方法后收到的只是一個到操作本身的引用,就像一個頂級菜單操作一樣,沒有包含與被選中的資源或始發(fā)控件有關的信息。資源引用實際上被提供給 selectionChanged 方法,而且必須被保存為一個實例變量,以備稍后使用——請參見清單 8。

清單 7. 運行 HSQLDB Script Tool
    public static void runScriptTool(IFile currentScript) throws CoreException {        PluginUi plugin = PluginUi.getDefault();        // destroys any preexisting configuration and create a new one        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();        ILaunchConfigurationType type = manager.getLaunchConfigurationType(            IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);        ILaunchConfiguration[] configurations = manager.getLaunchConfigurations(            type);        for (int i = 0; i > configurations.length; i++) {            ILaunchConfiguration config = configurations[i];            if (config.getName().equals("SQL Script")) {                config.delete();            }        }        ILaunchConfigurationWorkingCopy wc = type.newInstance(null,            "SQL Script");        // constructs a classpath from the default JRE...        IPath systemLibs = new Path(JavaRuntime.JRE_CONTAINER);        IRuntimeClasspathEntry systemLibsEntry =            JavaRuntime.newRuntimeContainerClasspathEntry(                systemLibs, IRuntimeClasspathEntry.STANDARD_CLASSES);        systemLibsEntry.setClasspathProperty(            IRuntimeClasspathEntry.BOOTSTRAP_CLASSES);        //... plus hsqldb.core plugin        IPluginRegistry registry = Platform.getPluginRegistry();        IPluginDescriptor hsqldbCore = registry.getPluginDescriptor(            "hsqldb.core");        ILibrary[] libs = hsqldbCore.getRuntimeLibraries();        String installDir = hsqldbCore.getInstallURL().toExternalForm();        URL hsqldbJar = null;        try {            hsqldbJar = Platform.asLocalURL(new URL(installDir +                libs[0].getPath()));        }        catch(Exception e) {            // ignore URL exceptions        }        IRuntimeClasspathEntry hsqldbEntry =            JavaRuntime.newArchiveRuntimeClasspathEntry(new Path(                hsqldbJar.getPath()));        hsqldbEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);        // sets the launch configuration classpath        List classpath = new ArrayList();        classpath.add(systemLibsEntry.getMemento());        classpath.add(hsqldbEntry.getMemento());        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH,            classpath);        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH,            false);        // current directory should be the script container        IPath dir = currentScript.getParent().getLocation();        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,            dir.toString());        // gets the path for the selected SQL script file        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,            "org.hsqldb.util.ScriptTool");        // builds ScriptTool command line        HsqldbParams params = getConnectionParams();        String args = "-driver org.hsqldb.jdbcDriver " +            "-url jdbc:hsqldb:hsql: " +            "-database //127.0.0.1:" + params.port + " " +            "-user " + params.user + " " +            "-script " + currentScript.getName();        if (params.passwd.length() > 0)            args += "-password " + params.passwd + " ";        wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,            args);        // saves the new config and launches it        ILaunchConfiguration config = wc.doSave();        DebugUITools.launch(config, ILaunchManager.RUN_MODE);    }            


清單 8. 如何得到要執(zhí)行的 SQL Script,來自 hsqldb.ui.popup.actions.HsqldbRunScript
    public void selectionChanged(IAction action, ISelection selection) {        currentScript = null;        if (selection != null) {            if (selection instanceof IStructuredSelection) {                IStructuredSelection ss = (IStructuredSelection)selection;                // as this action is enabled only for a single selection,                // it‘s enough to get the first element                Object obj = ss.getFirstElement();                if (obj instanceof IFile) {                    currentScript = (IFile)obj;                }            }        }    }            

HSQLDB 屬性
現(xiàn)在我們的插件的大部分功能都已經就位,僅僅缺少配置服務器連接參數(shù)的方法:它監(jiān)聽的 TCP 端口、管理員用戶名稱以及管理員用戶密碼。TCP 端口可能必須要改變,從而避免與安裝在開發(fā)人員機器上的其他應用程序發(fā)生沖突;用戶及密碼可以從任意客戶機上使用 SQL 語句來改變。這些參數(shù)可以被放入一個類似 C 結構(或類似 pascal 記錄)的名為 HsqldbParams 的類中, 如清單 9 所示。它也聲明了由 Plugin Preferences Store 和 Property Page 使用的常量來取得并保存參數(shù)(引用)值。

清單 9. 用于 HSQLDB 服務器連接參數(shù)的參數(shù)選擇結構
package hsqldb.ui;public class HsqldbParams {    // preference names for the plugin    public static final String P_PORT = "serverPort";    public static final String P_USER = "serverUser";    public static final String P_PASSWD = "serverPasswd";        public int port = 9001;    public String user = "sa";    public String passwd = "";}            

不幸的是,由 PDE New Extension Wizard 生成的參數(shù)選擇頁面類起了一點誤導作用,它包括一個方法,用于設置不會被插件參數(shù)選擇存儲使用的默認參數(shù)選擇值。初始化默認值的正確位置應該是主要的 Plugin 類本身。否則,所有使用默認值的參數(shù)選擇將被參數(shù)選擇存儲返回為 0 或 null。

因此,參數(shù)選擇頁面類變得簡單多了,如清單 10 所示,并且方法 initializeDefaultPreferences 被添加到 PluginUi 類中,如清單 11 所示。注意,每個參數(shù)選擇的默認值均由參數(shù)選擇結構定義,而不是由插件類或參數(shù)選擇頁面類來定義。

清單 10. HSQLDB 插件的參數(shù)選擇頁面
public class HSQLDBPreferencePage    extends FieldEditorPreferencePage    implements IWorkbenchPreferencePage {    public HSQLDBPreferencePage() {        super(GRID);        setPreferenceStore(PluginUi.getDefault().getPreferenceStore());        setDescription("Connection parameters for the embedded HSQLDB server");    }        public void createFieldEditors() {        addField(new IntegerFieldEditor(HsqldbParams.P_PORT,                 "&TCP Port:",                getFieldEditorParent()));        addField(new StringFieldEditor(HsqldbParams.P_USER,                "Administrator &User:",                getFieldEditorParent()));        addField(new StringFieldEditor(HsqldbParams.P_PASSWD,                "Administrator &Password:",                getFieldEditorParent()));    }        public void init(IWorkbench Workbench) {    }}            


清單 11. 來自生成的 Plugin 類的已更改方法
    public void shutdown() throws CoreException {        // shuts down the server if running        Thread server = getHsqldbServer();        if (server != null && server.isAlive()) {        		 try {                HsqldbUtil.stopHsqldb();            }            catch (Exception e) {                e.printStackTrace();            }        }        super.shutdown();    }    protected void initializeDefaultPreferences(IPreferenceStore store) {        super.initializeDefaultPreferences(store);        HsqldbParams params = new HsqldbParams();        store.setDefault(HsqldbParams.P_PORT, params.port);        store.setDefault(HsqldbParams.P_USER, params.user);        store.setDefault(HsqldbParams.P_PASSWD, params.passwd);    }               

提供反饋給用戶
由于插件組既沒有提供視圖也沒有提供編輯器給 Workbench,所以只有幾種有限的方法可以為用戶提供操作方面的反饋。我們可以使用 Workbench 窗口的狀態(tài)欄以及一個 SWT MessageDialog ,這樣用戶就不會錯過重要的事件(通常是錯誤)。

Workbench 操作的可見性及實現(xiàn)模型主要集中在工作區(qū)資源選擇方面,但是大部分插件操作(啟動及停止 HSQLDB 服務器,還包括啟動Database Manager)并不依賴于資源選擇,而是依賴于服務器是否正在運行——這個條件必須由每個操作的 run 方法進行顯式檢查。

警告: 插件類與操作類直到絕對需要降低 Workbench 對內存的需求時才會被初始化。清單文件內容被用于表示菜單選擇和啟用/禁用它們, 但是由于 HSQLDB 服務器不屬于工作區(qū)資源,所以它不能啟用操作。正如清單 2 中的清單代碼所描述的那樣,您可以(請參見 <enablement> 元素)在激活插件的基礎之上啟用/禁用一項操作,所以在啟動時只有“Start HSQLDB server” 操作可以被啟用,但在這之后如果服務器已經處于運行狀態(tài),則不存在容易的方法來禁用這項操作以及當其停止后重新啟用它。

注意,用于在 Workbench 窗口上放置一個沙漏狀光標的代碼,以及用于設置狀態(tài)欄消息的代碼不易在 PDE 文檔或 Eclipse.org 文章中找到。

最后一步
插件類重寫了 shutdown 方法,所以當 Workbench 被關閉時它能夠干凈利落地關閉服務器,這時我們就結束了整個過程。當然,要得到一個完整的插件組還需要完成這里沒有講到的額外任務,比如:

  • 把兩個插件包裝成一個功能,這樣它們就可以作為一個單元進行安裝、移除、啟用和禁用。
  • 為插件本身提供幫助文檔,并使用一種適合于 Workbench 幫助管理器的格式將 HSQLDB 文檔包含在其內。

結束語
本文介紹如何創(chuàng)建可將 HSQLDB 數(shù)據(jù)庫引入到 Eclipse Workbench 中的一組插件,以增添啟動和停止服務器以及運行 SQL 語句和腳本的能力。我們已經了解到 PDE 是如何使這類插件的創(chuàng)建工作變得容易的,即對大多數(shù)任務使用向導和編輯器,而留給開發(fā)人員的任務不過是創(chuàng)建真正實現(xiàn)所需功能的代碼。

在這個系列的下一個部分中,您將了解到如何利用 Workbench 的功能向 HSQLDB 開發(fā)添加值,而不僅僅是簡單地運行預先存在的工具。

參考資料


本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
org.eclipse.ui.plugin.AbstractUIPlugin 插件
開發(fā) Eclipse 插件
CSDN技術中心 教您如何創(chuàng)建、調試和安裝Eclipse插件
eclipse入門:開發(fā)eclipse插件
Eclipse 體系結構綜述(二)
Rich Ajax Platform,第 1 部分: 簡介
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服