ApacheFelixFramework启动和内嵌.docx
《ApacheFelixFramework启动和内嵌.docx》由会员分享,可在线阅读,更多相关《ApacheFelixFramework启动和内嵌.docx(21页珍藏版)》请在冰豆网上搜索。
ApacheFelixFramework启动和内嵌
启动和内嵌ApacheFelixFramework
【本文档是Felix2.0.0及最终版本的启动介绍;它兼容Felix框架的旧版本。
】
简介
Felix很容易启动和嵌入到其他应用程序。
例如,Felix避免使用系统属性进行配置,因此可以在同一个虚拟机中启动多个Felix实例。
Felix也建立了多个单例工厂,如URLstreamhandler工厂。
其总体目标是在广泛的范围内使用框架。
OSGI启动和嵌入式API概述
Felix实现了org.apache.felix.framewor.Felix类。
作为OSGI规范4.2的一部分,OSGI启动和嵌入式API已经标准化。
框架需要实现org.osgi.framework.launch.Framework接口(继承了org.osgi.framework.Bundle接口)。
此接口提供了必要的信息启动和管理框架实例。
Bundel接口定义如下:
publicinterfaceBundle
{
BundleContextgetBundleContext();
longgetBundleId();
URLgetEntry(Stringname);
EnumerationgetEntryPaths(Stringpath);
EnumerationfindEntries(Stringpath,StringfilePattern,booleanrecurse);
DictionarygetHeaders();
DictionarygetHeaders(Stringlocale);
longgetLastModified();
StringgetLocation();
URLgetResource(Stringname);
EnumerationgetResources(Stringname)throwsIOException;
ServiceReference[]getRegisteredServices();
ServiceReference[]getServicesInUse();
intgetState();
StringgetSymbolicName();
VersiongetVersion();
booleanhasPermission(Objectobj);
ClassloadClass(Stringname)throwsClassNotFoundException;
voidstart()throwsBundleException;
voidstop()throwsBundleException;
voiduninstall()throwsBundleException;
voidupdate()throwsBundleException;
voidupdate(InputStreamis)throwsBundleException;
}
Framework接口定义如下:
publicinterfaceFrameworkextendsBundle
voidinit();
FrameworkEventwaitForStop(longtimeout);
实际构造框架实例,R4.2规范定义了FrameworkFactory接口:
publicinterfaceFrameworkFactory
FrameworknewFramework(Mapconfig);
可以使用框架工厂类配置和建立框架实例。
通过标准的META-INF/services获得。
建立和配置框架实例
可以使用工厂类构造和配置框架实例(或者直接实例化Felix类)。
配置表包含任意框架配置属性(见Felix框架配置属性集),不包含启动配置属性。
配置属性大小写敏感。
构造框架后不能再改变框架配置。
如果需要不同的配置,必须建立新的框架实例。
启动框架实例
使用start()方法启动框架实例。
如果init()方法没有先于start()方法调用,start()方法会调用init()。
2个方法执行完使框架处于不同状态。
●init()框架实例在Bundle.STARTINT状态。
●start()框架实例在Bundle.ACTIVE状态。
框架第一次建立时,还没有BundleContext时,必须执行inti方法,所以转换到Bundle.STARTINT状态前必须要建立他的上下文(通过Bundle.getBundleContext()),执行几个任务,例如:
安装bundles。
注意,Felix也提供了felix.systembundle.activators属性也起到相同的作用,但不是标准的。
init方法执行完毕,需要执行下列操作:
●使能事件处理器
●如果使能安全,安装安全管理器
●所有bundle缓存中的bundle具体化,设为Bundle.INSTALLED状态
●框架获得一个合法的BundelContext
●所有osgi服务可用(如:
PackageAdmi、StartLevel等)
●框架进入Bundle.STARTINT状态
调用start方法启动框架实例,如果init方法是手工调用的。
已经启动框架后调用inint和start方法没有任何效果。
停止框架实例
调用stop()方法将异步停止框架实例。
使用watiForStop()方法等待框架完成终止动作。
停止的框架处于Bundle.RESOLVED状态。
可以使用init/start重启框架。
启动框架
启动框剪相当简单,仅需要4步:
1、定义些配置属性
2、获得框架工厂类
3、使用工厂类(包含配置属性)建立框架实例
4、调用Framework.start()方法
实际上,自所有的属性都有了缺省值,第一步是可选的,除非建立一个自定义的启动器,如自动安装和启动bundle。
Felix启动器默认自动安装和启动bundle;查看用户手册获得更多Felix配置属性信息。
下面的章节描述如何启动Felix以及自定义启动。
标准的Felix启动器
标准的Felix启动器很简单,不打算解决每一种需求;相反着重解决规范的情景。
大多数特殊的启动要求将建立自定义的启动器。
下列main()方法代码描述了标准的启动器,每行注释将描述更多细节:
publicstaticvoidmain(String[]args)throwsException
//
(1)Checkforcommandlineargumentsandverifyusage.
StringbundleDir=null;
StringcacheDir=null;
booleanexpectBundleDir=false;
for(inti=0;i{if(args[i].equals(BUNDLE_DIR_SWITCH)){expectBundleDir=true;}elseif(expectBundleDir){bundleDir=args[i];expectBundleDir=false;}else{cacheDir=args[i];}}if((args.length>3)||(expectBundleDir&&bundleDir==null)){System.out.println("Usage:[-b][]");System.exit(0);}//(2)Loadsystemproperties.Main.loadSystemProperties();//(3)Readconfigurationproperties.PropertiesconfigProps=Main.loadConfigProperties();if(configProps==null){System.err.println("No"+CONFIG_PROPERTIES_FILE_VALUE+"found.");configProps=newProperties();}//(4)Copyframeworkpropertiesfromthesystemproperties.Main.copySystemProperties(configProps);//(5)Usethespecifiedauto-deploydirectoryoverdefault.if(bundleDir!=null){configProps.setProperty(AutoProcessor.AUTO_DEPLOY_DIR_PROPERY,bundleDir);}//(6)Usethespecifiedbundlecachedirectoryoverdefault.if(cacheDir!=null){configProps.setProperty(Constants.FRAMEWORK_STORAGE,cacheDir);}//(7)Addashutdownhooktocleanstoptheframework.StringenableHook=configProps.getProperty(SHUTDOWN_HOOK_PROP);if((enableHook==null)||!enableHook.equalsIgnoreCase("false")){Runtime.getRuntime().addShutdownHook(newThread("FelixShutdownHook"){publicvoidrun(){try{if(m_fwk!=null){m_fwk.stop();m_fwk.waitForStop(0);}}catch(Exceptionex){System.err.println("Errorstoppingframework:"+ex);}}});}try{//(8)Createaninstanceandinitializetheframework.FrameworkFactoryfactory=getFrameworkFactory();m_fwk=factory.newFramework(configProps);m_fwk.init();//(9)Usethesystembundlecontexttoprocesstheauto-deploy//andauto-install/auto-startproperties.AutoProcessor.process(configProps,m_fwk.getBundleContext());//(10)Starttheframework.m_fwk.start();//(11)WaitforframeworktostoptoexittheVM.m_fwk.waitForStop(0);System.exit(0);}catch(Exceptionex){System.err.println("Couldnotcreateframework:"+ex);ex.printStackTrace();System.exit(0);}}一般,标准启动器很直接:1、启动器设置auto-deply目录(使用-b选项)、使用1个目录设置bundle缓存路径,所以检查参数大于1个。2、调入system.properties文件系统属性;这个文件典型的放在Felix安装目录下conf/中,也可以使用felix.system.properties系统属性配置。此文件时标准的java属性文件,使用${}语法支持代替方式。属性代替方式支持嵌入,仅系统属性能使用代替方式。3、调入config.properties文件中的配置信息,这个文件也放在conf/目录,也可以使用felix.config.properties系统属性配置。此文件建立启动器的配置信息。此文件也支持代替方式。4、习惯上,任何系统属性拷贝到配置属性集里,很容易增加和覆盖config.properties文件中的属性。5、如果启用了-b选项,将使用一个特定的auto-deploy目录,也可使用felix.auto.deploy.dir配置值。6、如果使用了一个单一的命令行参数,将使用它设置org.osgi.framework.storage;相对与当前目录的路径。除非设置了felix.cache.rootdir属性配置。7、增加停止钩子,除非禁止钩子。8、使用配置属性,通过FrameworkFactory建立框架实例,然后,初始化工厂实例;下面的自定义启动器示例描述了如何通过META-INF/services获得FrameworkFactory9、调用org.apache.felix.main.AutoProcessor,自动部署auto-deploy目录的bundle,根据felix.auto.install和felix.auto.start属性自动安装或启动bundle。10、调用waitForStop方法等待框架终止并退出虚拟机;这是必须的,因为框架永不会调用System.exit(),一些库(如,Swing)建立线程后不允许虚拟机退出。框架知道调用start方法激活。如果没有shellbundle安装启动的话,框架将悬挂运行,实际上,没有任何方式可以与它交互,shell仅提供了底层的交互。自定义框架启动器本节建立一个最小的启动器,演示一个最小需求、交互式的Felix启动器。本示例使用标准的Gogoshellbundle进行交互,当然也能使用其他bundle。本例项目结构如下:launcher/lib/org.apache.felix.main-3.0.0.jarbundle/mand-0.6.0.jarorg.apache.felix.gogo.runtime-0.6.0.jarorg.apache.felix.gogo.shell-0.6.0.jarsrc/example/Main.javalib/目录包含Felixmainjar文件,也包含OSGI核心接口。使用mainJAR文件可以重用缺省的启动器自动部署/自动启动配置属性处理器;如果不需要此功能,可以使用frameworJAR文件替换mainJAR文件。bundle/目录包含shell服务和文本shell接口bundle,可以通过它与框剪交互。注:如果没有交互式bundle,框架将悬挂运行。src/example/目录包含下面Main.java文件,是一个很简单的框架启动器:packageexample;importjava.io.*;importorg.osgi.framework.launch.*;importorg.apache.felix.main.AutoProcessor;publicclassMain{privatestaticFrameworkm_fwk=null;publicstaticvoidmain(String[]argv)throwsException{//Printwelcomebanner.System.out.println("\nWelcometoMyLauncher");System.out.println("======================\n");try{m_fwk=getFrameworkFactory().newFramework(null);m_fwk.init()AutoProcessor.process(null,m_fwk.getBundleContext());m_fwk.start();m_fwk.waitForStop(0);System.exit(0);}catch(Exceptionex){System.err.println("Couldnotcreateframework:"+ex);ex.printStackTrace();System.exit(-1);}}privatestaticFrameworkFactorygetFrameworkFactory()throwsException{URLurl=Main.class.getClassLoader().getResource("META-INF/services/org.osgi.framework.launch.FrameworkFactory");if(url!=null){BufferedReaderbr=newBufferedReader(newInputStreamReader(url.openStream()));try{for(Strings=br.readLine();s!=null;s=br.readLine()){s=s.trim();//Trytoloadfirstnon-empty,non-commentedline.if((s.length()>0)&&(s.charAt(0)!='#')){return(FrameworkFactory)Class.forName(s).newInstance();}}}finally{if(br!=null)br.close();}}thrownewException("Couldnotfindframeworkfactory.");}}启动器依赖AutoProcessor默认行为处理shellbundle自动部署。这个简单通用的启动器提供了一个起点,如果Felix启动器不够用。m_fwk=getFrameworkFactory().newFramework(null);m_fwk.init()本步是获得框架工厂服务,使用它建立默认配置的框架实例,并调用intit方法初始化。AutoProcessor.process(null,m_fwk.getBundleContext());AutoProcessor自动部署在auto-deploy目录的bundle,并处理自动install/start。如果是空配置,没有自动属性,auto-deploy目录是当前目录下的bundle目录。当前,shellbundle将被安装。m_fwk.start();m_fwk.waitForStop(0);System.exit(0);最后是启动框架,启动应用线程并等待框架终止,当应用线程调用System.exit(),虚拟机将退出。privatestaticFrameworkFactorygetFrameworkFactory()throwsException{...}此方法查找META-INF/services资源获得工厂类。如果使用Java6,可以使用JAE中的ServiceLoader简单获得工厂服务。下列命令在项目根目录编译启动器:javac-d.-classpathlib/org.apache.felix.main-3.0.0.jarsrc/example/Main.java执行这个命令后,example/目录在当前目录建立,包含生成的class文件。下面的命令在项目根目录执行简单的启动:java-cp.:lib/org.apache.felix.main-3.0.0.jarsrc/example/Main.java执行此命令后,“felix-cache”目录建立,包含缓存的bundle(是从bundle/目录安装的bundle)嵌入Felix框架把Felix嵌入一个宿主,是提供可扩展的机制(如:插件系统)的简单办法。嵌入Felix与上述描述类似,主要的不同是宿主想与框架实例和暴漏bundle/service交互。这有些微妙的不同点。本节描述宿主嵌入Felix的机制。宿主/Felix交互在上面启动框架时,Felix类接受felix.systembundle.activators配置属性(bundleactivator实例列表)。bundleactivator实例提供了宿主与Felix框剪交互的方法。每个activator实例实际变成了系统bundle的一部分。这意味着列表中每个activator实例start/stop方法在系统bundle激活时都被分别调用。每个activator实例提供了BundleContext对象,所以能与框架交互。看看下面bundleactivator片段:publicclassHostActivatorimplementsBundleActivator{privateBundleContextm_context=null;publicvoidstart(BundleContextcontext){m_context=context;}publicvoidstop(BundleContextcontext){m_context=null;}publicBundle[]getBundles(){if(m_context!=null){returnm_context.getBundles();}returnnull;}}现在可以嵌入Felix,下述片段演示了交互:publicclassHostApplication{privateHostActivatorm_activator=null;privateFeli
if(args[i].equals(BUNDLE_DIR_SWITCH))
expectBundleDir=true;
elseif(expectBundleDir)
bundleDir=args[i];
expectBundleDir=false;
else
cacheDir=args[i];
if((args.length>3)||(expectBundleDir&&bundleDir==null))
System.out.println("Usage:
[-b][]");
System.exit(0);
(2)Loadsystemproperties.
Main.loadSystemProperties();
//(3)Readconfigurationproperties.
PropertiesconfigProps=Main.loadConfigProperties();
if(configProps==null)
System.err.println("No"+CONFIG_PROPERTIES_FILE_VALUE+"found.");
configProps=newProperties();
//(4)Copyframeworkpropertiesfromthesystemproperties.
Main.copySystemProperties(configProps);
//(5)Usethespecifiedauto-deploydirectoryoverdefault.
if(bundleDir!
=null)
configProps.setProperty(AutoProcessor.AUTO_DEPLOY_DIR_PROPERY,bundleDir);
//(6)Usethespecifiedbundlecachedirectoryoverdefault.
if(cacheDir!
configProps.setProperty(Constants.FRAMEWORK_STORAGE,cacheDir);
//(7)Addashutdownhooktocleanstoptheframework.
StringenableHook=configProps.getProperty(SHUTDOWN_HOOK_PROP);
if((enableHook==null)||!
enableHook.equalsIgnoreCase("false"))
Runtime.getRuntime().addShutdownHook(newThread("FelixShutdownHook"){
publicvoidrun()
try
if(m_fwk!
m_fwk.stop();
m_fwk.waitForStop(0);
catch(Exceptionex)
System.err.println("Errorstoppingframework:
"+ex);
});
//(8)Createaninstanceandinitializetheframework.
FrameworkFactoryfactory=getFrameworkFactory();
m_fwk=factory.newFramework(configProps);
m_fwk.init();
//(9)Usethesystembundlecontexttoprocesstheauto-deploy
//andauto-install/auto-startproperties.
AutoProcessor.process(configProps,m_fwk.getBundleContext());
//(10)Starttheframework.
m_fwk.start();
//(11)WaitforframeworktostoptoexittheVM.
System.err.println("Couldnotcreateframework:
ex.printStackTrace();
一般,标准启动器很直接:
1、启动器设置auto-deply目录(使用-b选项)、使用1个目录设置bundle缓存路径,所以检查参数大于1个。
2、调入system.properties文件系统属性;这个文件典型的放在Felix安装目录下conf/中,也可以使用felix.system.properties系统属性配置。
此文件时标准的java属性文件,使用${}语法支持代替方式。
属性代替方式支持嵌入,仅系统属性能使用代替方式。
3、调入config.properties文件中的配置信息,这个文件也放在conf/目录,也可以使用felix.config.properties系统属性配置。
此文件建立启动器的配置信息。
此文件也支持代替方式。
4、习惯上,任何系统属性拷贝到配置属性集里,很容易增加和覆盖config.properties文件中的属性。
5、如果启用了-b选项,将使用一个特定的auto-deploy目录,也可使用felix.auto.deploy.dir配置值。
6、如果使用了一个单一的命令行参数,将使用它设置org.osgi.framework.storage;相对与当前目录的路径。
除非设置了felix.cache.rootdir属性配置。
7、增加停止钩子,除非禁止钩子。
8、使用配置属性,通过FrameworkFactory建立框架实例,然后,初始化工厂实例;下面的自定义启动器示例描述了如何通过META-INF/services获得FrameworkFactory
9、调用org.apache.felix.main.AutoProcessor,自动部署auto-deploy目录的bundle,根据felix.auto.install和felix.auto.start属性自动安装或启动bundle。
10、调用waitForStop方法等待框架终止并退出虚拟机;这是必须的,因为框架永不会调用System.exit(),一些库(如,Swing)建立线程后不允许虚拟机退出。
框架知道调用start方法激活。
如果没有shellbundle安装启动的话,框架将悬挂运行,实际上,没有任何方式可以与它交互,shell仅提供了底层的交互。
自定义框架启动器
本节建立一个最小的启动器,演示一个最小需求、交互式的Felix启动器。
本示例使用标准的Gogoshellbundle进行交互,当然也能使用其他bundle。
本例项目结构如下:
launcher/
lib/
org.apache.felix.main-3.0.0.jar
bundle/
mand-0.6.0.jar
org.apache.felix.gogo.runtime-0.6.0.jar
org.apache.felix.gogo.shell-0.6.0.jar
src/
example/
Main.java
lib/目录包含Felixmainjar文件,也包含OSGI核心接口。
使用mainJAR文件可以重用缺省的启动器自动部署/自动启动配置属性处理器;如果不需要此功能,可以使用frameworJAR文件替换mainJAR文件。
bundle/目录包含shell服务和文本shell接口bundle,可以通过它与框剪交互。
注:
如果没有交互式bundle,框架将悬挂运行。
src/example/目录包含下面Main.java文件,是一个很简单的框架启动器:
packageexample;
importjava.io.*;
importorg.osgi.framework.launch.*;
importorg.apache.felix.main.AutoProcessor;
publicclassMain
privatestaticFrameworkm_fwk=null;
publicstaticvoidmain(String[]argv)throwsException
//Printwelcomebanner.
System.out.println("\nWelcometoMyLauncher");
System.out.println("======================\n");
m_fwk=getFrameworkFactory().newFramework(null);
m_fwk.init()
AutoProcessor.process(null,m_fwk.getBundleContext());
System.exit(-1);
privatestaticFrameworkFactorygetFrameworkFactory()throwsException
URLurl=Main.class.getClassLoader().getResource(
"META-INF/services/org.osgi.framework.launch.FrameworkFactory");
if(url!
BufferedReaderbr=newBufferedReader(newInputStreamReader(url.openStream()));
for(Strings=br.readLine();s!
=null;s=br.readLine())
s=s.trim();
//Trytoloadfirstnon-empty,non-commentedline.
if((s.length()>0)&&(s.charAt(0)!
='#'))
return(FrameworkFactory)Class.forName(s).newInstance();
finally
if(br!
=null)br.close();
thrownewException("Couldnotfindframeworkfactory.");
启动器依赖AutoProcessor默认行为处理shellbundle自动部署。
这个简单通用的启动器提供了一个起点,如果Felix启动器不够用。
本步是获得框架工厂服务,使用它建立默认配置的框架实例,并调用intit方法初始化。
AutoProcessor自动部署在auto-deploy目录的bundle,并处理自动install/start。
如果是空配置,没有自动属性,auto-deploy目录是当前目录下的bundle目录。
当前,shellbundle将被安装。
最后是启动框架,启动应用线程并等待框架终止,当应用线程调用System.exit(),虚拟机将退出。
...
此方法查找META-INF/services资源获得工厂类。
如果使用Java6,可以使用JAE中的ServiceLoader简单获得工厂服务。
下列命令在项目根目录编译启动器:
javac-d.-classpathlib/org.apache.felix.main-3.0.0.jarsrc/example/Main.java
执行这个命令后,example/目录在当前目录建立,包含生成的class文件。
下面的命令在项目根目录执行简单的启动:
java-cp.:
lib/org.apache.felix.main-3.0.0.jarsrc/example/Main.java
执行此命令后,“felix-cache”目录建立,包含缓存的bundle(是从bundle/目录安装的bundle)
嵌入Felix框架
把Felix嵌入一个宿主,是提供可扩展的机制(如:
插件系统)的简单办法。
嵌入Felix与上述描述类似,主要的不同是宿主想与框架实例和暴漏bundle/service交互。
这有些微妙的不同点。
本节描述宿主嵌入Felix的机制。
宿主/Felix交互
在上面启动框架时,Felix类接受felix.systembundle.activators配置属性(bundleactivator实例列表)。
bundleactivator实例提供了宿主与Felix框剪交互的方法。
每个activator实例实际变成了系统bundle的一部分。
这意味着列表中每个activator实例start/stop方法在系统bundle激活时都被分别调用。
每个activator实例提供了BundleContext对象,所以能与框架交互。
看看下面bundleactivator片段:
publicclassHostActivatorimplementsBundleActivator
privateBundleContextm_context=null;
publicvoidstart(BundleContextcontext)
m_context=context;
publicvoidstop(BundleContextcontext)
m_context=null;
publicBundle[]getBundles()
if(m_context!
returnm_context.getBundles();
returnnull;
现在可以嵌入Felix,下述片段演示了交互:
publicclassHostApplication
privateHostActivatorm_activator=null;
privateFeli
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1