使用NetBeans6开发OSGi应用(3)——整合Knopflerfish![88250原创]
转载请保留作者信息:
作者:88250
Blog:http:/blog.****.net/DL88250
MSN & Gmail & QQ:[email protected]
摘要
上一次,我们编写了两个Bundles,一个是服务提供商,一个是使用服务的客户 ,运行得还不错 :-)这一次,我们先简要分析一下KF(Knopflerfish)框架的设计,学习应用程序框架的设计。最后,结合上一次文章结尾时提到了关于控制KF框架、让OSGi服务于我们的应用的问题,今天就围绕这些内容展开。
关于Knopflerfish框架的设计
在开始,我们将看一下KF框架的设计。Main
在阅读了KF框架的一些代码后,从KF框架的主程序入手(org.knopflerfish.framework.Main)我们可以看出,KF除了实现OSGi规范,实现了自己的framework(org.knopflerfish.framework.Framework)外,主要是围绕它的框架启动类:org.knopflerfish.framework.Main做了一系列的铺垫:比如所实现的OSGi规范的版本(我的版本是OSGi 4.0.6版本),存储Bundle的文件位置,操作系统版本,等等。这个Main类,主要做的是命令行参数(启动参数)的处理,因为KF框架启动的时候可以用xargs文件(把所有参数写成一个文件),所以处理上比较繁琐。在Main下面的handleArgs方法可以看出,所有的Bundles的基本操作(start、stop、install、etc.)都是调用org.knopflerfish.framework.Framework这个类实现的,这个类就是KF框架的基本实现,已经把功能封装地相当好用了!
那我们应该直接使用Framework类吗?
我们应该直接使用KF实现的Framework类,但是整个框架的启动铺垫是很繁琐的。从Main还有其相关的Utils的代码量就可以看出。在整个框架启动之前,要做一系列的铺垫。这里,结合我自己的项目,由于时间比较紧了,再重写这些可能时间不允许,所以我选择的是改写Main,把那个Main类作为自己应用框架的一个对KF的基本封装。具体做法就是委托Framework类的一些方法,暴露这些方法在Main外部。
总之,要基于Knopflerfish,完成自己的一个应用框架还是比较简单的 :-)
让我们简单实践一下!
准备
同上一次 :-)开工:
1. 创建工程
打开NB6,创建一个普通Java应用工程——MyOSGiFramework:注意那个version文件,这个文件是指KF实现的OSGi的版本,在OSGi框架实现里,有一个Version类,用于版本的管理。要在我们的src目下建立一个version文件。
2.改写Knopflerfish的Main类
添加对Bundle的基本操作到Main类里,达到封装KF框架的目的。下面是添加的一些示例方法:
/**
*Getthebundlecontextusedbythesystembundle.
*@returnsystem<code>BundleContext</code>
*/
publicstaticBundleContextgetBundleContext(){
returnframework.getSystemBundleContext();
}
/**
*Startabundle.
*@paramidIdofbundletostart
*/
publicstaticvoidstartBundle(longid){
try{
framework.startBundle(id);
}catch(BundleExceptionex){
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);
}
}
/**
*Stopabundle.
*@paramidIdofbundletostop
*/
publicstaticvoidstopBundle(longid){
try{
framework.stopBundle(id);
}catch(BundleExceptionex){
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);
}
}
*Getthebundlecontextusedbythesystembundle.
*@returnsystem<code>BundleContext</code>
*/
publicstaticBundleContextgetBundleContext(){
returnframework.getSystemBundleContext();
}
/**
*Startabundle.
*@paramidIdofbundletostart
*/
publicstaticvoidstartBundle(longid){
try{
framework.startBundle(id);
}catch(BundleExceptionex){
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);
}
}
/**
*Stopabundle.
*@paramidIdofbundletostop
*/
publicstaticvoidstopBundle(longid){
try{
framework.stopBundle(id);
}catch(BundleExceptionex){
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);
}
}
这里,做的工作就是“纯”委托。
编写我们对Main的测试类:
/*
*@(#)MainTest.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
packagemyosgiframework;
importorg.knopflerfish.framework.Main;
importorg.osgi.framework.Bundle;
importorg.osgi.framework.BundleContext;
/**
*Atestcaseof<code>org.knopflerfish.framework.Main</code>.
*<p>
*Baseonknopflerfishframework,modifysomesourcein<code>Main</code>,
*annotatethesemodificationswith<code>@since</code>mark,
*markas<tt>@since4.0.6</tt>.
*</p>
*@author88250
*@version1.0.0.0,Feb15,2008
*/
publicclassMainTest{
/**
*Programentrypoint.
*@paramargsshouldbe<code>null</code>
*/
publicstaticvoidmain(String[]args){
Main.main(args);
Main.startBundle(1);
displayBundlesStatus();
Main.stopBundle(1);
displayBundlesStatus();
Main.shutdown(0);
}
privatestaticvoiddisplayBundlesStatus(){
BundleContextbc=Main.getBundleContext();
Bundle[]b=bc.getBundles();
for(inti=0;i<b.length;
i++){
Bundlebundle=b[i];
System.out.println("ID:#"+bundle.getBundleId()+
"Location:"+bundle.getLocation()+
"Status:"+bundle.getState());
}
}
}
*@(#)MainTest.java
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion3oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNULibraryGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace-Suite330,Boston,MA02111-1307,USA.
*/
packagemyosgiframework;
importorg.knopflerfish.framework.Main;
importorg.osgi.framework.Bundle;
importorg.osgi.framework.BundleContext;
/**
*Atestcaseof<code>org.knopflerfish.framework.Main</code>.
*<p>
*Baseonknopflerfishframework,modifysomesourcein<code>Main</code>,
*annotatethesemodificationswith<code>@since</code>mark,
*markas<tt>@since4.0.6</tt>.
*</p>
*@author88250
*@version1.0.0.0,Feb15,2008
*/
publicclassMainTest{
/**
*Programentrypoint.
*@paramargsshouldbe<code>null</code>
*/
publicstaticvoidmain(String[]args){
Main.main(args);
Main.startBundle(1);
displayBundlesStatus();
Main.stopBundle(1);
displayBundlesStatus();
Main.shutdown(0);
}
privatestaticvoiddisplayBundlesStatus(){
BundleContextbc=Main.getBundleContext();
Bundle[]b=bc.getBundles();
for(inti=0;i<b.length;
i++){
Bundlebundle=b[i];
System.out.println("ID:#"+bundle.getBundleId()+
"Location:"+bundle.getLocation()+
"Status:"+bundle.getState());
}
}
}
3. 测试
还记得上一次我们的那个Bundle吗?为了它启动在我们的框架里,编写一个启动参数文件secondosgi.xargs:
然后,修改启动参数:
测试输出: