通過使用 Eclipse 插件開發環境(Eclipse Plug-in Development Environment,PDE),WebSphere Studio 能讓您快速開發功能強大的插 件。然而,在您開始新的插件開發項目時,擺在您面前的功能和選擇會使您無從選擇。本文提供了在插件開發過程中您將面對的這些問題的實 踐概要,無論您選擇使用的是 WebSphere Studio 或是 vanilla Eclipse。
引言
插件的相關性以及與其有關的在團隊中共享項目方式理解起來是比較復雜的。或許 Eclipse 的強大和深度意味著您學習起來會很費勁。本 文將集中討論在共享插件環境項目開發時會遇到的常見問題,以及如何利用 Eclipse 插件開發環境(PDE)。
本文從 Eclipse 插件框 架和使用源代碼儲存庫進行代碼共享的概要開始,然後舉例說明在跨團隊共享插件代碼時會出現的問題,例如在構建路徑控制時。還將討論環 境的建立和如何最大程度的利用 IBM® WebSphere® Studio Application Developer V5.1.1 and V5.1.2 (以下稱為 Application Developer)。這裡討論的內容同樣適用於 Application Developer 所基於的 Eclipse 2.1 環境。Eclipse 的早期和晚期版本之間的差別將被 提到 —— 要檢查您的產品版本,請選擇 Help =>About。
Eclipse 插件體系結構
Application Developer 以開 放源代碼 Eclipse 項目為基礎。Eclipse 自身由多層 功能(一個功能就是一組插件)構成。Eclipse 的功能強大之處遠不止通過插件添加新 的功能。它能按以前從未想到的方式擴展其他人員的貢獻。這需要穩健的機制來聲明和下載插件。以下將通過范例來講述有關的細節。范例 shop 應用程序如下所示。這四個插件(日志、數據倉庫、業務邏輯和用戶接口)都包含一個可安裝的功能:
圖 1. 范例應用程序的插 件關聯結構
在圖框之間的箭頭表示著插件之間的相關性(在核心 Eclipse 組件之間也同樣存在相關性,例如 org.eclipse.ui )。每個插件在 清單( plugin.xml )文件中定義了它與庫文件(.JAR 文件)和其他插件的相關性。在此關鍵的一點是類裝載由 Eclipse 控制,並且每個插件擁有自 己的類裝載器。插件只能加載自身清單已定義的那些資源。
源代碼儲存庫
Application Developer 提供了共享代碼的多種方式;例如 Project Interchange Files。然而,在任何團隊開發項 目中,SCM (Software Configuration Management)或者如 CVS 的儲存庫是必需的,這樣所有團隊成員就能保持步調一致。Application Developer 對此提供了強大的功能(比如 Team 上下文菜單上的 Synchronize)。參見參考資料部分以獲取與此主題有關的文章鏈接。
全部共享
在儲存庫中實現共享能帶來豐厚的利益。理論上,對於每個插件,您將存儲:
源文件(.java)
源數據文件(.classpath、plugin.xml、.project,以及其他類似文件)
單元測試文件 (數據和源代碼)
引用的二進制庫
構建文件(build.properties 或 build.xml)
為什麼要進行盡可能多的檢入(check-in)呢?主要有兩大主要理由。第一,如 果團隊將共享最大化,那麼能在系統之間變化的便所剩無幾了。例如,通過共享構建文件可以減少由於在團隊中封裝方法的變更而導致的問題 。問題已經浮出水面,特別是有關類路徑的問題。我將在本文的後面將會處理其中的一些問題。
第二,儲存庫將提供版本支持。在使用 現有的(或者第三方)庫時會有極大的好處。例如,我的 com.example.shop.datastore 插件中的數據庫。調試有關不相容的庫之間出現的問 題是很費時間的,而且這些問題可以通過版本控制顯著減少。該想法可以推廣到許多領域,包括:
已完成的插件/功能構建和環境詳細 信息
基本測試/構建腳本
項目/產品文檔,許可證和類似資料
其他開發環境數據
可以共享的環境信息的例子是 Eclipse 首選項,例如在 Java™ 部分中的“Code Formatter”、“Editor Templates”和“Code Generation”部分。這些都在 Window =>Preferences 下可以找到,並且可以用 XML 方式導出。好處是可以共享代碼標准,而且整個 團隊都能從這些靈活的 Java 編輯器選項中獲益。
當然,細節部分會因存儲數據方式的限制而變化。例如,對於存儲文檔、已完成的部 分和其他構建的位置和方式,您的組織會有自己的約定。
解析插件的相關性
插件在自身的清單中定義了相關性。如以下摘要所 示,圖 1 中的 com.example.shop.ui 插件就依賴於 com.example.shop.log 和 com.example.shop.logic 。
<plugin
id="com.example.shop.ui"
...
<runtime>
<library name="ui.jar"/>
</runtime>
<requires>
<import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.ui"/>
<import plugin="com.example.shop.logic"/>
<import plugin="com.example.shop.log"/>
</requires>
...
PDE 自動估計要求類路徑的庫(參見 Preferences =>Plug-in development =>Java build path control)。在開發過程中,該數據存儲在 .classpath 文件中。以下是有關 com.example.shop.ui 插件的范例:
<classpath>
<classpathentry kind="src" path="src/"/>
<classpathentry kind="var"
path="ECLIPSE_HOME/plugins/org.eclipse.core.resources_2.1.1/resources.jar" ... >
<classpathentry kind="src" path="/com.example.shop.logic"/>
<classpathentry kind="src" path="/com.example.shop.log"/>
...
核心 Eclipse 相關性 resources.jar 通過平台的 plugins 目錄解析,而我的兩個插件被解析為項目引用。該范例說明了 PDE 如何在清單中解析相關性來為 com.example.shop.ui 插件建立開發類路徑 。
提示:通過從帶三角形圖標的下拉菜單中選擇 Filters 可以防止 Package Explorer 隱藏 .classpath 和其它點前綴的(dot- prefixed)文件。在該菜單中還有其他很多有用的選項。
共享項目
如果您想在人員和機器之間共享整個項目,有許多選項可以 實現。請參見參考資料部分有關共享資源和 CVS 團隊開發的文章。
在 Application Developer 中,在您從 CVS 檢出(check out)或 從文件系統導入一組項目之後,您將會發現一些構建錯誤。這些通常是未解析的插件或庫(忽略代碼問題)。在上文中 .classpath 范例中, 可以發現它包含有關項目名稱和插件庫版本的特定條目。不幸的是,庫版本隨 Application Developer 版本的不同而有差別,如以下所示。另 外,不能找到 com.example.shop.logic 插件是因為我在新工作區為該項目取了另外的名字。
圖 2. 無效的插件庫引用
好消息是您可以告訴 Application Developer 進行自我修復!
修復已損壞的引用——更新類路徑
要更新許多項 目的類路徑,右鍵單擊 plugin.xml 文件或 Package Explorer 中的一組項目,並選擇 Update classpath。在 Eclipse 的最新版本中,選擇 PDE tools =>Update classpath同樣可以更新 Dependencies 頁面上插件清單編輯器中的單個插件類路徑。然後,您需要根據構建首選項進 行構建。
圖 3 . 更新類路徑以修復未解析的相關性
毫無疑問,在更新後,這些錯誤就肯定消失了。
提 示:當您看見 The import **** cannot be resolved 信息出現在先前運行良好的環境中時,請不要嘗試選擇 Organize imports。當這些信息 出現時,通常時因為找不到庫而不是源代碼有錯誤的導入語句。如果您在庫不能進行解析時使用該指令,您最終將移除正確的導入,最壞的情 況是,您將會獲得那些有同樣不合格名稱的不正確的導入。
引用現有的二進制庫(.JAR 文件)
假設您現有一個 Java 類的庫( 例如名叫 logger.jar ),而您的插件依賴這個庫,那麼您可以:
將 logger.jar 復制到每個使用該文件的插件中。
創建實用 插件以封裝 logger.jar 。
第一個選項是最簡單的,但是不希望在項目周圍出現許多庫的副本——即使在版本控制下。因此 使用第二個選項使其他插件通過日志插件來訪問 logger.jar 會更好些。
在圖 1 中, com.example.shop.log 插件提供了日志來支持 其他插件。在插件項目和其他通常的 Java 項目之間一個很大的的區別是如何在完全部署好的配置中提供類路徑。當插件安裝好後,它的類裝 載器的類路徑不是硬編碼,而是當啟動時基於 plugin.xml 文件由平台得出的。因此您必須在清單中聲明庫,因為無論如何 .classpath 文件 都將被忽略。
圖 4 . 在插件清單(plugin.xml)編輯器中引用現有的庫
來自 plugin.xml 清單的摘錄展示了插件如何包含已編譯的源代碼(log.jar)和 logger.jar 庫(保存在項目的 lib 子文件夾中的儲存庫 中)。
<plugin
id="com.example.shop.log"
...
<runtime>
<library name="log.jar">
<export name="*"/>
<packages prefixes="com.example.shop.log,com.example.shop.log.actions"/>
</library>
<library name="lib/logger.jar">
<export name="*"/>
<packages prefixes="org.logco"/>
</library>
...
提示:為更快速的類裝載指定包前綴(參見以上 plugin.xml 中< packages > 部分)。
圖 5 . Log 插件的 src 文件夾中的包和 lib/logger.jar 庫
提示:將任何附加的文件(例如, lib/logger.jar )指 定包含在插件導出中,並在 build.properties 文件編輯器中通過編輯 bin.includes 屬性封裝操作。這在您編輯 Runtime 頁面是通常會更新 。
提示:通常您必須強制更新類路徑來解析清單中的庫。參見上文中的“修復損壞的引用 -- 更新類路徑”。
選擇 導出選項
我使用 Export the entire library 選項,這樣其他的插件可以直接在 logger.jar 庫中引用類。當其他插件的代碼企圖從 logger.jar 裝載類時,將通過 com.example.shop.log 插件的類裝載器對其進行解析(可以激活尚未激活的 Log 插件)。
提示:通過 使用 Export using content filters 只導出必要的已發布資源給其他插件。這將導致類似於 <export name="org.logco.*"/> 的條目 出現在 plugin.xml 中。
導出庫的備選方案是為 logger.jar 庫頂部的其他插件提供 facade。這樣的接口可以使其他插件使用日志特 征,而無須直接耦合到庫,並提供更多的自由度來更改實現庫,而不會干擾相關的插件。當然,這意味著需要更多的工作量以實現該接口。
混合二進制和源插件項目
如果您的項目或開發組中只有很好的插件(例如圖 1 中所示),您將可能把它們都視為工作區中的標 准源項目。Application Developer 將通過在平台中第一次搜索工作區中及外部的插件來解析插件的相關性(例如,解析 org.eclipse.core.resources )。
源項目 工作區中的標准 Eclipse 項目,包含編輯和構建的源代碼。外部插件 通常是一組可用於您 的開發環境的插件,例如 Application Developer 自帶的插件在您的 ECLIPSE_HOME 目錄中。
提示:使用 PDE 透視圖中的 Plug-ins 視圖來浏覽外部插件。您可以使用選中插件的彈出式菜單來將插件添加到 Java 搜索機制。這使您可以浏覽 Jar 並在 Open Type Hierarchy 對話框中查看類型。
然而,在開發組環境中,很多情況下您不希望每個插件都作為完整的源項目:
您有許多很少變動的插件, 所以只需要作為二進制相關性。
開發組有大量的插件,每個成員只使用其中的一部分插件。
構建所有的插件源代碼需要很長的 時間。
當然,這些情況並不互相排斥,但它們表現的更像項目的依賴關系樹。很有可能您將希望只編輯小部分插件,但依靠更大的插件 組來進行構建和搜索。為此,Eclipse 有了二進制插件項目的概念。
二進制插件項目 工作區插件項目沒有源文件夾,但其他方面卻類 似於正規的源項目。例如,它可以被浏覽和搜索。
在下面的圖 6 中,我將 Logging 插件安裝到 Application Developer,這樣當開發 其他三個插件時,可以將其作為二進制組件使用。您也可以通過使用 Import =>External Plug-ins and Fragments 選項來創建二進制項目 。參見參考資料中的文章“Put Eclipse features to work for you”,這篇文章描述了如何安裝插件,而不會打亂您的產品安裝 目錄。
圖 6. 在 Plug-ins 視圖中導入外部插件作為二進制項目
除了浏覽很方便之外,使用基於外部插件的二進制項目的 真正優點是它可以使類路徑更加穩定。如果您看了“解析插件相關性”中的 .classpath 示例,您會發現工作區項目和外部插件的 類路徑條目的存儲各不相同。實際上,類路徑條目對於源項目和二進制項目來說是相同的,因為它們都是保存在工作區中。這意味者盡管有源 項目和二進制項目的不同組合,開發人員也可以共享 .classpath 文件。
大型項目的插件類型組合范例
插件類 型 建議的插件 源項目 被個別組件或在功能性組件中使用的少量插件。 二進制項 目 通常被源項目浏覽或使用的更大的插件組。這可能是項目或擴展 Eclipse 部分的更大的組件。 外部插件 項目的其他插件,以及平台上的插件。其中一些更相關的插件可以添加到 Java 搜索中。
提示:開啟二 進制項目標記 decorator 以使其區別於源項目 — 它們使用“01”decorator。參見圖 7。使用 Window =>Preferences =>Workbench =>Label Decorations。
圖 7. 在您的工作區中使用源項目和二進制項目
提示:使用 Package Explorer 下拉菜單中的 Filters 選 項來顯示或隱藏二進制項目。
提示:使用 Working Sets 來將插件項目組合為便於使用的類別。Working Sets 可以用來在 Package Explorer、Tasks 視圖中過濾,並可用於一些操作。
使用動態類路徑 —— 類路徑容器
您可能會想與不同的項目配 置相關的類路徑是如何的復雜。如果 Application Developer 能夠為您給出的設置測算 .classpath 文件,那麼這裡面的條目又有什麼用呢? 由於所有的內容都在運行時和開發時通過 plugin.xml 清單來驅動,環境難道不應該在後台完成這些工作嗎?
不錯,好消息是它確實可 以。Application Developer V5.1.1 包含了容器管理類路徑功能(在 Eclipse 2.1 和 Eclipse 3.0 缺省配置中可用),它解決本文描述的許 多問題。使用該功能,類路徑基於插件清單自動更新,不管您使用的是源項目、二進制項目還是外部插件,它都可以為您完成這些工作。
要使用該功能,選擇 Plug-in development =>Java build path control preferences並選中 Use classpath containers。然後您 將需要更新插件的類路徑。
圖 8. 為關聯插件使用類路徑容器
現在您可以監視每個插件所需庫中的間接性級別。在 .classpath 文件 中,所有的庫條目都與一個用於類路徑容器的條目放在一起:
<classpath>
<classpathentry kind="src" path="src/"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
現在 PDE 將在內部用自動且可靠的方式管理工作區或外部的庫。您可以在開發組中非常方便的共享那些 .classpath 和 .project 文件!
控制相關性
隨著您的項目的進展,保持跟蹤多個插件相關性將變得更加困難。為了對此進行幫 助,Application Developer 可以:
查找未使用的插件相關性。
查找相關性所涉及的范圍。
圖 9. 估算相關性的使用
圖 9 展示了 com.example.shop.ui 插件使用 com.example.shop.log 插件類的次數。該特征是非常有用的,因為您可以查看一個插件在其他插件中使用的 深度。它能顯示令人驚奇的結果。
Find unused dependencies選項提供了那些從未使用的插件完整的列表。減少不必要的相關性可以在 運行時提供效率。
結束語
管理任何產品中的相關性都是一項艱難的工作。Eclipse 插件結構與其插件開發環境為構建復雜的標 准組件的軟件產品提供了強大的工具。Eclipse 解決了解析相關性帶來的許多困難。但是學習掌握起來還是比較費勁的。使用 Eclipse 2.1 , 容器管理類路徑功能可以保護開發人員避免不同配置的差別、靈活性的漸增以及設置的簡單化而帶來的問題。
在 Eclipse 3.0 中, 所有插件使用動態類路徑。該功能以及其他新的功能將會使團隊開發更加容易(參見頁底 “參考資料” 中的 Eclipse.org 鏈接以獲取更多相關信息)。
共享項目的開發環境可以為自身提供更多的時間用來開發代碼。Application Developer 同樣為您提供了調試、構建和測試插件的靈活的選擇。請至“參考資料”部分以查閱有關跟蹤、診斷運行時問題以及通 過 Application Developer 使用 Ant 的相關文章。用正規的構建和測試來組合產品的開發設置將使您能夠快速且平穩的進行插件項目開發。