输出的package自动的列入Import-Package中,这个特性可通过在Export-Package中添加一个特殊的directive来取消:-noimport:=true,例如:
Export-Package= com.acme.impl.*;-noimport:=true, *
这个参数和Export-Package的使用方法相同,唯一不同的就是在这里指定的packages是不对外暴露的,这个头信息只是复制到
manifest中而已。如果一个包既在Export-Package里定义了,又在Private-Package里定义了,那么将会做为
Export-Package。
Private-Package= com.*
Import-Package用来指定需要引用的packages。默认值为\'*\',也就是导入所有引用的packages,因此Import-
Package很少被设置。但在某些特殊的情况下可能会不希望引用某些包,因为这些包其实从来就没用到过,在这种情况下可以使用过滤模式来实现,还有一种
就是需要导入没有明确定义需要引用的package(例如采用Class.forName方式加载的类),这种就需要手工在Import-Package
中来定义,否则bnd是不会自动生成。
例如:
Import-Package: !org.apache.commons.log4j, com.acme.*,
com.foo.extra
在处理过程中,bnd会尝试寻找引用的packages导出时所指定的版本。如未定义引用package的版本或版
本范围,bnd就会使用导出版本的基本版本号。
例如导出的版本为1.2.3.build123,那么导入的版本为1.2.3,如指定了导入的版本或版本范围,那么bnd将使用找到的符合的版本来覆盖,
在版本范围的定义中${@}可用来代表找到的范围内的版本。
Import-Package: org.osgi.framework;version=\"[1.3,2.0)\"
Import-Package: org.osgi.framework;version=\"[${@},2.0)\"
Include Resources指定需要复制到目标jar文件中的资源文件。有以下几种方式来定义:
iclause ::= inline | copy
copy ::= \'{\' process \'}\' | process
process ::= assignment | simple
assignment ::= PATH \'=\' PATH
simple ::= PATH
inline ::= \'@\' PATH ( \'!/\' PATH? (\'/**\' | \'/*\')? )?
对于assignment或simple而言,可通过设置PATH参数指定文件或目录。也可以使用 classpath中JAR文件的name.ext路径,也就是说,忽略目录。simple方式采用的是直接把文件不带目录的放入目标jar文件中,例 如,工程中有src/a/b.c文件,以simple方式处理的话bnd将会把b.c直接放到目录JAR文件的根目录下。
如资源文件必须放在目标JAR中的子目录下,可以使用assignment方式来实现。 如文件未找到,bnd将会寻找整个classpath来查找是否有匹配的文件。 inline参数必须是ZIP或JAR文件, 文件可以指定为jar中的具体的文件名,或者为一个带**或*的目录。**表示在查找时采用的为递归查询的方式,*则只在指定的目录下查找,如仅指定了目录名,就相当于目录名**。
simple和assigment方式都可以使用{}的方式,使用{}的这种文件意味着是会被率先处理的,同样也可以使用变量或宏定义,关于变量和宏定义请参见macro章节。
Include-Resource: @osgi.jar,
{LICENSE.txt}, acme/Merge.class=src/acme/Merge.class
Service-Component头信息和标准的OSGi
的头信息是兼容的。在列表中未带属性的元素必须相应的有资源文件在Jar中,并且该元素信息会复制到manifest中。组件定义的标识为:
component ::= <implementation-class> ( \';\' parameter ) *
parameter ::= provide | reference | multiple | optional
reference | properties | factory | servicefactory
| immediate | enabled
reference ::= <name> \'=\' <interface-class>
provide ::= \'provide:=\' LIST
multiple ::= \'multiple:=\' LIST
optional ::= \'optional:=\' LIST
dynamic ::= \'dynamic:=\' LIST
factory ::= \'factory:=\' true | false
servicefactory := \'servicefactory:=\' true | false
immediate ::= \'immediate:=\' true | false
enabled ::= \'enabled:=\' true | false
properties::= \'properties:=\' key \'=\' value
( \',\' key \'=\' value ) *
组件名也就是实现的类名。之后为其引用的服务,每个服务的名称对应的为ComponentContext .cate.html' target='_blank'>locateService 中调用的服务名,如果名称以小写开头,则被认为是bean属性,在这种情况下,这个引用将按照set<名称>和unset<名 称>的标准bean规则来使用。Bnd负责解析这个头信息,并在输出的jar文件的OSGI-INF目录下创建一个<id>.xml的 文件。
下面的例子演示了一个通过setLog来调用log服务的组件的头信息的定义方法:
Service-Component=aQute.tutorial.component.World;
log=org.osgi.service.log.LogService
在Declarative
Services的规范中SCR还提供了很多的附加选项的支持。有些选项像target是不支持的,但像policy和cardinality是支持的,
如果这个引用是optional性质的,那么应该在optional声明中进行定义,这也就意味着cardinality从0开始。如该组件需要引用服务
接口的多个实现,则需要在multiple声明中定义。policy是通过dynamic声明来定义的,需要dynamic引用的就在dynamic声明
中定义。SCR赋的默认值为:1..1的cardinality和static的policy。看一个复杂的例子:
Service-Component=aQute.tutorial.component.World;
log=org.osgi.service.log.LogService
;
http=org.osgi.service.http.HttpService
;
dynamic:=\'log,http\';
optional:=log;
PROCESSORS=xierpa.service.processor.Processor;
multiple:=PROCESSORS;
properties:=\"wazaabi=true\"
根据上面的方式编写的头信息bnd产生一个OSGI-INF/aQute.tutorial.component.World.xml文件,文件的内容为:
<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<component name=\"aQute.tutorial.component.World\">
<implementation class=\"aQute.tutorial.component.World\" />
<reference name=\"log\"
interface=\"org.osgi.service.log.LogService
\"
cardinality=\"0..1\"
bind=\"setLog\"
unbind=\"unsetLog\"
policy=\"dynamic\" />
<reference name=\"http\"
interface=\"org.osgi.service.http.HttpService
\"
bind=\"setHttp\"
unbind=\"unsetHttp\"
policy=\"dynamic\" />
<reference name=\"PROCESSORS\"
interface=\"xierpa.service.processor.Processor\"
cardinality=\"1..n\" />
</component>
在头信息的描述里还支持immediate、enabled、factory和servicefactory属性。如需了解这些属性的信息,请参见Declarative Services。
宏定义处理器可用于对头信息进行复杂的处理。宏变量可使用单一定义的值,也可使用复杂的函数。每个头信息都相当于一个可扩展的宏,作为宏的头信息是
不以大写字母开头的,也不会复制到manifest中去,因此他们也可被当成宏变量而使用。可通过${<name>}(大括号方式)
或$(<name>)(小括号方式)来引用变量。另外,也可以使用[]、<>、《》和??。
例如:
version=1.23.87.200109111023542
Bundle-Version= ${version}
Bundle-Description= This bundle has version ${version}
bnd默认的设置了一些属性值:
| 属性名 | 说明 |
|---|---|
| project | 工程名,默认为去除.bnd后的文件名,如文件名为bnd.bnd,则采用bnd文件所在的目录名。 |
| project.file | bnd文件的绝对路径。 |
| project.name | 所在的绝对路径的文件名称。 |
| project.dir | bnd 文件所在的目录的绝对路径。 |
bnd自带了一些实现基本功能的macros。采用如下格式使用和定义函数:
macro ::= \'${\' function \'}\'
| function
| \'$(\' function \')\'
| \'$<\' function \'>\'
| \'$?\' function \'?\'
| \'$?\' function \'?\'
function ::= name ( \':\' argument ) *
| 函数 | 参数 | 说明 |
|---|---|---|
| filter | ; list ; regex | filter遍历所有给定的值,并只包含符合这些正则表达式的元素。下面的例子演示了如何用filter来实现只包含list中的jar文件: list= a,b,c,d,x.jar,z.jar List= ${filter;${list};.*\\.jar} |
| filterout | ; list ; regex | filterout遍历所有给定的值,并去除符合这些正则表达式的元素。下面的例子演示了如何用filterout来实现去除list中的jar文件: list= a,b,c,d,x.jar,z.jar List= ${filterout:${list};.*\\.jar} |
| sort | ; list | Sort用于实现把所有的元素按字母排序。例如: List= ${sort:acme.jar, harry.jar, runner.jar, alpha.jar, bugs.jar} |
| join | ( ; list ) * | Join用来实现把元素集合合并为同
一个集合。看起来这个功能用两个宏直接连接起来也可以实现,但除非是用,隔开两个集合的元素,否则用两个宏直接连接形成的将不是list,但如果其中的一
个集合元素为空,则会出现错误。join则很好的处理了这种情况,join可支持给定的任何数量的元素集合的合并,例如: List= ${join;a,b,c;d,e,f} |
| if | ; condition ; true ( ; false ) ? | 如果条件不为空,则返回true对应的值,如为空,则返回false对应的值,如未设置false对应的值,则返回空字符串,条件在运行前会做去空格处理。例如: Comment: ${if;${version};Ok;Version is NOT set!!!!} |
| now | 以字符串形式返回当前日期,例如: Created-When: ${now} |
|
| fmodified | ; file-path-list | 返回给定的文件路径的最近的修改时间。这个函数是基于Java提供的API所编写的,所以其返回值为long类型。例如: Last-Modified: ${long2date;${fmodified;${files}}) |
| long2date | ; long | 把long类型转换为date类型,例如: Last-Modified: ${long2date:${fmodified:${files}}) |
| replace | ; list ; regex ; replacement | 替换符合表达式的值。函数基于item.replaceAll实现。如需给所有的文件添加.jar的扩展名,可使用如下方法实现: List = ${replace;${impls};$;.jar} |
| toclassname | ; list | 把类文件(如:org/osgi/service/LogService .class)转换为类名(如org.osgi.service.LogService )。 |
| toclasspath | ; list | 把类名(如org.osgi.service.LogService )转换为类文件名(org/osgi/service/LogService .class)。 |
| findname | ; regex [ ; replacement ] | 寻找到符合表达式的资源的路径,并将资源的名称以给定的值替换。仅用于替换资源的名称,并不包含/。 |
| findpath | ; regex [ ; replacement ] | 寻找到符合表达式的资源的路径,并将资源的路径以给定的值替换,在替换时包含/。 |