<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    在OSGi容器外和OSGi進(jìn)行交互

    在使用OSGi時(shí),有些時(shí)候會(huì)需要在OSGi容器外獲取OSGi服務(wù),加載OSGi容器加載的class,或者說(shuō)需要內(nèi)嵌OSGi容器,本篇blog以一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明如何基于equinox實(shí)現(xiàn)OSGi容器的內(nèi)嵌,或者說(shuō)通過(guò)程序來(lái)啟動(dòng)equinox,同時(shí)也通過(guò)此例子展示下如何在容器外來(lái)獲取OSGi服務(wù)以及加載OSGi容器里面其他插件的class,同時(shí)還會(huì)附送一個(gè)如何讓OSGi容器里的插件能加載到OSGi容器外的類(lèi)的方法。

    對(duì)于用過(guò)equinox的同學(xué),或者看過(guò)我之前那兩篇OSGi opendoc附帶的例子的同學(xué)而言,都會(huì)知道通過(guò)命令行來(lái)啟動(dòng)equinox的方式,常見(jiàn)的一種腳本為:java -jar plugins/org.eclipse.osgi_3.2.1.R32x_v20060919.jar -configuration configuration -console,然后在當(dāng)前目錄的configuration目錄下放置一個(gè)config.ini,在此config.ini中通過(guò)osgi.bundles=來(lái)配置需要加載和啟動(dòng)的插件,例如osgi.bundles=a.jar@start,那么要在程序中啟動(dòng)equinox容器,其實(shí)基本是差不多的。

    查看equinox的代碼,會(huì)看到調(diào)用上面的org.eclipse.osgi.jar后執(zhí)行的是EclipeStarter中的靜態(tài)run方法,因此只需在外部傳入合適的參數(shù),并調(diào)用此run方法即可完成equinox的啟動(dòng),在程序中啟動(dòng)equinox,通常希望做到的是能夠指定config.ini的配置信息以及插件的位置,而不是由equinox去決定,如果不進(jìn)行設(shè)置,默認(rèn)情況下EclipseStarter將會(huì)在工作路徑下產(chǎn)生configuration,并以該configuration目錄下的config.ini作為equinox啟動(dòng)的配置,對(duì)于osgi.bundles配置的bundle的路徑,默認(rèn)則為當(dāng)前EclipseStarter代碼所在的目錄,例如上面的命令行,equinox在啟動(dòng)時(shí)就會(huì)從plugins目錄中去加載插件,這通常是無(wú)法滿(mǎn)足在程序中啟動(dòng)equinox的需求的,如果想自定義equinox啟動(dòng)的配置信息,而不是通過(guò)去加載指定的configuration中的config.ini,那么可以在程序中調(diào)用FrameworkProperties.setProperty來(lái)設(shè)置啟動(dòng)equinox的配置信息,如希望指定osgi.bundles中指定的加載的bundle的相對(duì)路徑,那么可以在equinox啟動(dòng)的配置信息中增加osgi.syspath的指定,F(xiàn)rameworkProperties.setProperty("osgi.syspath",你希望指定的bundle所在的路徑),equinox啟動(dòng)的配置信息還有很多種,具體有需要的話(huà)可以查看EclipseStarter中processCommandLine的方法,通過(guò)這樣的方式后,就可以采用類(lèi)似這樣的方式來(lái)啟動(dòng)equinox:EclipseStarter.run(new String[]{"-console"},null);按照上面這樣的方式就可以實(shí)現(xiàn)在外部程序中啟動(dòng)equinox了。

    OSGi通過(guò)BundleContext來(lái)獲取OSGi服務(wù),因此想在OSGi容器外獲取OSGi服務(wù),首要的問(wèn)題就是要先在OSGi容器外獲取到BundleContext,EclipseStarter中提供了一個(gè)getSystemBundleContext的方法,通過(guò)這個(gè)方法可以輕松的拿到BundleContext,而通過(guò)BundleContext則可以容易的拿到OSGi服務(wù)的實(shí)例,不過(guò)這個(gè)時(shí)候要注意的是,如果想執(zhí)行這個(gè)OSGi服務(wù)實(shí)例的方法的話(huà),還是不太好做的,因?yàn)槿萜魍獾腸lassloader和OSGi服務(wù)實(shí)例的class所在的classloader并不相同,因此不太好按照java對(duì)象的方式直接去調(diào)用,更靠譜的是通過(guò)反射去調(diào)用。

    如果想在容器外獲取到OSGi容器里插件的class,一個(gè)可選的做法是通過(guò)BundleContext獲取到Bundle,然后通過(guò)Bundle來(lái)加載class,采用這樣的方法加載的class就可以保證其是相同的,否則會(huì)出現(xiàn)容器外的一個(gè)A.class會(huì)不等于容器里插件的A.class,這個(gè)原因?qū)τ谏晕⒅纉ava classloader機(jī)制的人都理解的。

    按照上面的說(shuō)法,一個(gè)簡(jiǎn)單的啟動(dòng)Equinox以及與OSGi容器交互的類(lèi)可以這么寫(xiě):
       /**
         * 啟動(dòng)并運(yùn)行equinox容器
         
    */
        
    public static void start() throws Exception{
            
    // 根據(jù)需要加載的bundle組裝出類(lèi)似a.jar@start,b.jar@3:start這樣格式的osgibundles字符串來(lái)
            String osgiBundles="";
            
    // 配置Equinox的啟動(dòng)
            FrameworkProperties.setProperty("osgi.noShutdown""true");
            FrameworkProperties.setProperty(
    "eclipse.ignoreApp""true");
            FrameworkProperties.setProperty(
    "osgi.bundles.defaultStartLevel""4");
            FrameworkProperties.setProperty(
    "osgi.bundles", osgiBundlesBuilder.toString());
            
    // 根據(jù)需要設(shè)置bundle所在的路徑
            String bundlePath="";
            
    // 指定需要加載的plugins所在的目錄
            FrameworkProperties.setProperty("osgi.syspath", bundlePath);
            
    // 調(diào)用EclipseStarter,完成容器的啟動(dòng),指定configuration目錄
            EclipseStarter.run(new String[]{"-configuration","configuration","-console"}, null);
            
    // 通過(guò)EclipeStarter獲取到BundleContext
            context=EclipseStarter.getSystemBundleContext();
        }
        
        
    /**
         * 停止equinox容器
         
    */
        
    public static void stop(){
            
    try {
                EclipseStarter.shutdown();
                context
    =null;
            } 
            
    catch (Exception e) {
                System.err.println(
    "停止equinox容器時(shí)出現(xiàn)錯(cuò)誤:"+e);
                e.printStackTrace();
            }
        }
        
        
    /**
         * 從equinox容器中獲取OSGi服務(wù)instance   還可以基于此進(jìn)一步處理多服務(wù)接口實(shí)現(xiàn)的狀況
         * 
         * 
    @param serviceName 服務(wù)名稱(chēng)(完整接口類(lèi)名)
         * 
         * 
    @return Object 當(dāng)找不到對(duì)應(yīng)的服務(wù)時(shí)返回null
         
    */
        
    public static Object getOSGiService(String serviceName){
            ServiceReference serviceRef
    =context.getServiceReference(serviceName);
            
    if(serviceRef==null)
                
    return null;
            
    return context.getService(serviceRef);
        }
        
        
    /**
         * 獲取OSGi容器中插件的類(lèi)
         
    */
        
    public static Class<?> getBundleClass(String bundleName,String className) throws Exception{
            Bundle[] bundles
    =context.getBundles();
            
    for (int i = 0; i < bundles.length; i++) {
                
    if(bundleName.equalsIgnoreCase(bundles[i].getSymbolicName())){
                    
    return bundles[i].loadClass(className);
                }
            }
        }

    在實(shí)現(xiàn)了OSGi容器外與OSGi交互之后,通常會(huì)同時(shí)產(chǎn)生一個(gè)需求,就是在OSGi容器內(nèi)的插件要加載OSGi容器外的類(lèi),例如OSGi容器內(nèi)提供了一個(gè)mvc框架,而Action類(lèi)則在OSGi容器外由其他的容器負(fù)責(zé)加載,那么這個(gè)時(shí)候就會(huì)產(chǎn)生這個(gè)需求了,為了做到這點(diǎn),有一個(gè)比較簡(jiǎn)單的解決方法,就是編寫(xiě)一個(gè)Bundle,在該Bundle中放置一個(gè)允許設(shè)置外部ClassLoader的OSGi服務(wù),例如:
    public class ClassLoaderService{
         
         public void setClassLoader(ClassLoader classloader);
      
    }
    然后基于上面的方法,在外部啟動(dòng)equinox的類(lèi)中去反射執(zhí)行ClassLoaderService這個(gè)OSGi服務(wù)的setClassLoader方法,將外部的classloader設(shè)置進(jìn)來(lái),然后在OSGi容器的插件中需要加載OSGi容器外的類(lèi)的時(shí)候就調(diào)用下這個(gè)ClassLoaderService去完成類(lèi)的加載。

    基于以上說(shuō)的這些方法,基本上是可以較好的實(shí)現(xiàn)OSGi容器與其他容器的結(jié)合,例如在tomcat中啟動(dòng)OSGi等,不過(guò)在動(dòng)態(tài)化這塊就沒(méi)有那么好處理了,除非外部的容器也能提供相應(yīng)的動(dòng)態(tài)的機(jī)制,具體在下一篇的blog中再來(lái)細(xì)致的討論下OSGi的動(dòng)態(tài)化。

    posted on 2009-04-24 21:10 BlueDavy 閱讀(7087) 評(píng)論(11)  編輯  收藏 所屬分類(lèi): OSGi、SOA、SCA

    評(píng)論

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-25 02:21 Link

    好文!

    這里,我有一個(gè)問(wèn)題,假如我做一個(gè)RCP程序或者一個(gè)Eclipse插件,然后把你的用EclipseStarter.run()來(lái)啟動(dòng)一個(gè)OSGi框架的代碼放在插件中,總會(huì)產(chǎn)生錯(cuò)誤。

    java.lang.IllegalStateException: Platform already running
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:172)

    我猜想RCP程序與一般的應(yīng)用程序不同,在RPC程序中,RPC程序其于OSGi,OSGi平臺(tái)已經(jīng)啟動(dòng),在插件中EclipseStart對(duì)應(yīng)的是已經(jīng)運(yùn)行的這個(gè)RCP程序自身的OSGi框架,在RCP插件中再使用EclipseStarter.run()來(lái)啟動(dòng)另外一個(gè)OSGi框架的時(shí)候,就會(huì)出現(xiàn)“Platform already running"的錯(cuò)誤。

    之所以我需要這么做,我是想做基于RCP界面的一個(gè)OSGi框架運(yùn)行的監(jiān)控程序,在RCP界面上控制OSGi框架上各個(gè)Bundle的啟動(dòng)停止等,相當(dāng)于OSGi控制臺(tái)的可視化版本。這里的問(wèn)題好象就歸結(jié)到如何在一個(gè)OSGi框架內(nèi)使用代碼啟動(dòng)另一個(gè)OSGi框架,并返回被啟動(dòng)OSGi框架的BundleContext對(duì)象。

    請(qǐng)問(wèn)BlueDavy,就這個(gè)問(wèn)題,能給我一些幫助和建議嗎?  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-26 00:02 BlueDavy

    @Link
    恩,如果是在RCP里再調(diào)用EclipseStarter來(lái)啟動(dòng)肯定是不行的,因此如果是在RCP里的話(huà),你可以通過(guò)直接調(diào)用EclipseStarter.getSystemBundleContext,然后在界面上也可以通過(guò)這個(gè)BundleContext獲取到所有的bundle,進(jìn)而通過(guò)Bundle接口控制Bundle的生命周期。  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-26 00:42 Link

    @BlueDavy
    看來(lái)真的沒(méi)有辦法啟動(dòng)另一個(gè)程序。如果按你回復(fù)中的做法,將得到RCP程序本身的OSGi總線(xiàn)上的交互信息,返回的BundleContext得到的bundle也是RCP程序本身總線(xiàn)上的bundle。里面加雜了也許我并不需要監(jiān)控的bundle,沒(méi)有辦法達(dá)到我所說(shuō)的:可視化的OSGi控制臺(tái)的效果。  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-26 19:23 BlueDavy

    @Link
    另外一個(gè)做法是:可以自己通過(guò)context來(lái)install插件,這些插件就可以自己來(lái)管理了,具體可以參見(jiàn)我以前寫(xiě)過(guò)的一篇TPF的文章。
      回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-27 20:35 Link

    @BlueDavy 剛剛看了TPF的源代碼,大概知道了你開(kāi)發(fā)TPF的思路。TPF作為了一個(gè)本身獨(dú)立的程序,自身也運(yùn)行在OSGi總線(xiàn)上。安裝于OSGi總線(xiàn)上的TPF bundle再去管理OSGi總線(xiàn)上的其他bundle,并提供start/stop等控制功能。事實(shí)上,TPF Web界面顯示的已安裝的bundle列表只是TPF內(nèi)部維護(hù)的一個(gè)列表,在界面顯示的bundle后面,OSGi總線(xiàn)實(shí)際上已經(jīng)安裝了16個(gè)bundle。這些先期安裝的bundle在某些情況下是有可能影響本身希望在總結(jié)上部署的bundles的,比如某些版本沖突。
    TPF利用了自己運(yùn)行的總線(xiàn),作為一個(gè)希望以RCP做界面的類(lèi)TPF程序,如果也希望利用自己的總線(xiàn),即使不使用EclipseStart的方法,按TPF的思路,先期安裝的bundle的數(shù)目更多,可能的影響也許更大。一直想找一個(gè)另起一個(gè)OSGi總線(xiàn)的辦法而不得其解。曾經(jīng)想運(yùn)用Runtime.exec()另起一個(gè)“干凈”的總線(xiàn),但同時(shí)要拿到總線(xiàn)的BundleContext也不可行。 :(
      回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-27 21:39 BlueDavy

    @Link
    如果這樣的話(huà),或者可以考慮下自己做個(gè)OSGi Service,然后讓所有的bundle都實(shí)現(xiàn)下這個(gè)標(biāo)識(shí)性質(zhì)的service...不太優(yōu)雅的做法,:)
    另外一個(gè)方法,就是基于擴(kuò)展點(diǎn)模式來(lái)做。  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-30 01:50 Link

    @BlueDavy
    突然間有一個(gè)想法,Eclipse插件開(kāi)發(fā)時(shí),從開(kāi)發(fā)的Eclipse平臺(tái)運(yùn)行一個(gè)包含正在開(kāi)發(fā)的插件的運(yùn)行時(shí)的平臺(tái),這個(gè)好象就是從一個(gè)OSGi總線(xiàn)啟動(dòng)另一個(gè)OSGi總線(xiàn)的例子。不知道它是怎么做的?  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-04-30 09:15 BlueDavy

    @Link
    那應(yīng)該是外部啟進(jìn)程了,猜測(cè)而已...
      回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-06-04 16:33 shuhao

    link 你好,我現(xiàn)在也在做一個(gè)rcp使用osgi的開(kāi)發(fā),希望能與你交流。  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-06-04 16:35 shuhao

    呵呵,剛忘記了留聯(lián)系方式,qq:546187553
    也希望做過(guò)這個(gè)方面的高手指點(diǎn)。  回復(fù)  更多評(píng)論   

    # re: 在OSGi容器外和OSGi進(jìn)行交互 2009-06-23 13:20 zjg_robin

    如何在config.ini中指定目錄格式的bundle?如何寫(xiě)法?我的寫(xiě)法如下:
    file\:bundles/org.eclipse.core.runtime.compatibility.registry_3.2.200.v20080610@start

    啟動(dòng)時(shí)報(bào)錯(cuò),ZipError:error in opening zip file

    謝謝!  回復(fù)  更多評(píng)論   

    公告

     









    feedsky
    抓蝦
    google reader
    鮮果

    導(dǎo)航

    <2009年4月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    統(tǒng)計(jì)

    隨筆分類(lèi)

    隨筆檔案

    文章檔案

    Blogger's

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲AV噜噜一区二区三区| 成年女人色毛片免费看| 91成人免费福利网站在线| 国产成人综合亚洲| 男男gay做爽爽免费视频| 久久亚洲精品高潮综合色a片| 亚洲夂夂婷婷色拍WW47| 亚洲精品乱码久久久久久V| 亚洲人成电影网站色www| 亚洲欧美日韩中文二区| 亚洲AV无码成人精品区日韩| 污网站在线观看免费| 一区二区三区AV高清免费波多| 日韩久久无码免费毛片软件| 国产免费内射又粗又爽密桃视频| 久久久久久久久久久免费精品| 精品多毛少妇人妻AV免费久久| 中文在线免费不卡视频| 国产免费一区二区三区在线观看| 免费视频精品一区二区三区| 99爱视频99爱在线观看免费| 国产大片免费网站不卡美女| 成人免费无码视频在线网站| 最好免费观看韩国+日本| 亚洲av无码天堂一区二区三区| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲精品偷拍无码不卡av| 亚洲国产精品综合福利专区| 亚洲国产日韩视频观看| 亚洲欧美在线x视频| 国产国产人免费人成成免视频 | 亚洲不卡中文字幕| 亚洲Av无码国产一区二区| 一个人免费观看www视频| 免费国产叼嘿视频大全网站| 在线看免费观看AV深夜影院| 日韩视频在线免费| 亚洲乱码无码永久不卡在线| 亚洲网址在线观看你懂的| 中文无码亚洲精品字幕| 永久免费观看黄网站|