• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    利用 OSGi 解決 Eclipse 插件難題

    發布: 2007-5-24 22:43 | 作者: Bob Balfe | 來源: IBM | 查看: 72次 | 進入軟件測試論壇討論

    領測軟件測試網 本文介紹如何在代碼中為其他插件編寫擴展,而不是用 Eclipse V3.2 的動態擴展 API 創建對其他插件的依賴性?墒褂瞄_放服務網關協議 (Open Services Gateway Initiative,OSGi) 服務 API 和動態 API 完成所有這些任務甚至更多任務。

    本文介紹了一個采用 XML 的插件示例,以便為定義好的擴展點注冊擴展。通過使插件能夠感知 Extention Registry 并提供 OSGi 服務,我們可以完成這一完整的組件退耦操作。

    插件、擴展點、OSGi

    如您所知,Eclipse 的組件架構是基于插件 的 -- 這意味著將一組代碼組件化為單一的組件,然后利用 Eclipse 框架注冊為其組件之一,其他組件可以綁定該組件或調用該組件。擴展點 是插件允許其他插件向公開擴展點的插件提供附加功能的方法,F在利用所有這些插件并將其包裝到受控的運行時,插件可在其中動態進出,并且您可以獲得 OSGi(基本上來說)。

    示例插件

    讓我們從公開擴展點的基本插件開始,這樣可以為同義詞服務注冊新的字符串映射。此項服務允許其他服務注冊一個詞并將其映射到另一個詞(同義詞);緮U展包含非常簡單的元素:一個詞,當然還有一個新的同義詞。此插件擴展點的基本結構如表 1 所示。


    表 1. 示例插件的元素
    插件名稱 com.company.SynonymRegistry
    擴展點 同義詞
    元素 詞 -- 您想要為其添加同義詞的詞
    同義詞 -- 您想要注冊的同義詞

    我們還要將插件注冊為 OSGi 服務。這意味著它只在顯式執行此操作時被加載,并將可供其他客戶聲明性地使用。為了使用該服務,其他客戶只需了解 Interface 和 OSGi 類名稱。在我們的示例中,我們不會真正調用該服務,因為擴展點是假設的。我們將使用 OSGi API 以告知我們此項服務出入的時間,所以我們可以正確地注冊擴展點。

    現在這只是一個示例,并且使用針對此概念的擴展點可能不是最好的方法。我們用此基本示例要達到的目的是如何動態注冊新的擴展,同時說明使用 OSGi API 的插件生命周期事件。

    Mediator 插件

    下一個插件是第三方插件,該插件了解已知的服務和擴展點,但不想綁定到此插件,因為后面它將依靠該插件進行運行時解析。這意味著該插件可以駐留在所引用的插件 (com.company.SynonymRegistry) 可能不存在的機器上。因為我們現在生活在 OSGi 和動態運行時世界,所以我們想確保插件在不引起運行時故障或錯誤的情況下運行。我們的 mediator 插件將接受同義詞的 XML 文件,并且通過使用提供的擴展點用 SynonymRegistry 插件注冊每個同義詞。


    清單 1. 用于概念驗證的示例 XML 文件
    Synonyms.xml
                <?xml version="1.0" encoding="UTF-8"?>
                <synonyms>
                <entry word="mediator" synonym="broker"/>
                <entry word="mediator" synonym="go-between"/>
                <entry word="mediator" synonym="interceder"/>
                <entry word="mediator" synonym="intermediary"/>
                <synonyms>
                

    Mediator 插件在其 start() 方法中做的第一件事是用 OSGi 服務注冊為一個服務初始化偵聽器。我們要在傳入 start() 方法的 BundleContext 對象上調用 OSGi 服務方法 addServiceListener()。以下代碼展示了一個通過傳入代碼和我們感興趣的服務 ID 調用此 API 的示例。

    context.addServiceListener( this, "com.company.SynonymRegistry" );
                

    通過提供過濾器,可以告知 OSGi 服務注冊中心只需通知您指定服務中的狀態更改。在本例中,過濾器只是 SynonymRegistry 類的類名稱。

    您可能會尋根究底。答案就在啟動序列中。在 OSGi 領域,我們不是總知道另一服務可用的時間,因此我們需要對此進行說明。通過注冊為服務偵聽器,我們可得知服務開始和停止的時間。如果服務不可用,則允許我們緩存同義詞。當服務確實可用時,我們會得到通知并注冊擴展。

    注冊新擴展

    下面我們將講述本文的核心內容,F在我們有了想為其提供動態擴展的數據 (Synonyms.xml) 和已知的擴展點 (com.company.SynonymRegistry. Synonym)。由于我們不知道何時初始化插件,也不知道是否初始化 Synonym 插件,所以我們只要在加載插件時嘗試注冊 XML 文件中的條目即可。請記。哼@是一個展示概念的示例,不應在生產代碼中這樣實施。通常,我們盡可能多地以惰性方式(延遲或在需要時)執行初始化。

    Eclipse V3.2 中的新特性是能夠在運行時提供擴展。例如,客戶可以編寫一個包含某個視圖的應用程序,該視圖可以在單擊按鈕時創建一個透視圖。透視圖被添加到擴展注冊表,然后在可用透視圖的列表中顯示。此功能的重要好處之一是它可以減輕插件之間的“硬”依賴性。插件 A 可供在插件 B 中定義的平臺使用,無需依賴插件 B。而且,通過將此功能與 OSGi 框架結合,插件可以檢查服務的存在性,如果存在,可從服務中定義的擴展點創建擴展。這在使用面向服務架構的原則同時,促進了真正動態的環境。

    Eclipse V3.2 中新公開的是 addContribution() 方法,該方法在 IExtensionRegistry 接口中定義。清單 2 中的代碼展示了可以通過 addContribution() API 添加擴展的方法。addContribution() 方法旨在采用普通 XML 作為第一個參數中的 InputStream。


    清單 2. 通過 addContribution() API 添加擴展的方法
    IExtensionRegistry registry = RegistryFactory.getRegistry( );
                Object key = ((ExtensionRegistry) registry).getTemporaryUserToken( );
                ByteArrayInputStream is =
                new ByteArrayInputStream( buffer.toString().getBytes() );
                try {
                registry.addContribution(is, bundle, null, null, key);
                }
                finally {
                try {
                is.close( );
                }catch (IOException e) {
                }
                }
                

    編寫本文的時候 -- 意味著這是一個更改 Eclipse 未來版本的好機會 -- 允許公眾訪問注冊表的用戶標記可以使用此內部 Eclipse 調用獲得。下面的代碼展示了內部 API (getTemporaryUserToken()) 的使用。

    Object key = ((ExtensionRegistry)registry).getTemporaryUserToken();
                

    但是,在里程碑式的下一版本 Eclipse V3.2 版本中,此標記不能公開訪問。為了支持應用程序中的動態擴展,啟動程序必須提供以下針對虛擬機的設置:

    -Declipse.registry.nulltoken=true
                

    此定義現在允許我們將 null 用作 addContribution() API 中的 User Token,F在,我們的代碼看上去類似如下。有關此問題中的 Bugzilla 對話,請參見 Bugzilla bug 清單。


    清單 3. getTemporaryUserToken()
    ...
                try {
                registry.addContribution(is, bundle, null, null, null);
                }
                ...
                

    上面顯示的緩沖區變量表示實際的 XML 塊。此 XML 是我們可以在 plugin.xml 文件內看到的精確副本;氐轿覀兊 SynonymRegistry 示例,此擴展的 XML 將類似清單 4。


    清單 4. SynonymRegistry 的 XML
    <plugin>
                <extension point="com.company.synonymregistry" id="myExtension">
                <synonyms
                word="mediator"
                synonym="broker"/>
                </extension>
                </plugin>
                

    客戶可以考慮創建一個接受以下參數的包裝工廠類,如擴展點 ID、擴展 ID、元素名稱(本例中是同義詞)、實際屬性和資源包 ID。該包裝類將參數格式化為類似上面代碼的 XML 字符串。然后將此 XML 字符串讀入將被傳入到 IExtensionRegistry 接口的 addContribution() 方法的 ByteArrayInputStream 中。只有此方法的其他必需參數是用戶標記和資源包 ID。值得注意的一點是,資源包 ID 應是做出該貢獻的資源包的 ID,不是在其中定義擴展點的資源包的 ID。

    警告和提示

    在 M5(于 2006 年 2 月 17 日構建的 Eclipse)中引入的一個特性是,對 addContributions() 的調用是異步調用。這意味著該擴展不可立即使用,因為 Eclipse 啟動了一項執行實際注冊的作業。簡單地說,您必須開始自己的作業并與之同步,以獲得任何類型的同步行為。

    為了使此項任務更容易,下面給出了三條提示:

    • 創建一項將其本身注冊為一個 RegistryChangeListener 的新作業。
    • 該作業運行時,確保您的作業代碼偵聽 RegistryListener 回調的 isRegistered 集合。
    • 一旦所有注冊完成,即退出您的作業。

    當然,現在我們必須將調用代碼與生成的作業結合起來,以獲得同步調用。這只有在代碼要求立即使用擴展時才得到保證。希望您的代碼設計為惰性,這樣初始化就變得不重要。

    結束語

    動態擴展的使用可以通過編程方式創建。通過使用 OSGi 框架偵聽服務何時可用(加載或卸載),動態擴展增強了退耦功能。一起使用這些技術將允許聲明性的貢獻和組件之間 100% 退耦。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>