3.7 Resolving Process
Resolving is the process that creates a wiring between bundles. Constraints on the wires are statically defined by:
• Import and export packages (the DynamicImport-Package header is ignored in this phase)
• Required bundles, which import all exported packages from a bundle as defined in Requiring Bundles on page 65.
• Fragments, which provide their contents and definitions to the host as defined in Fragment Bundles on page 68
解析是bundle間建立連接的過程。連接上的約束的定義來(lái)自:
• 引入和輸出包(頭DynamicImport-Package在這個(gè)階段被忽略)
• Required bundles,從一個(gè)bundle那引入所有輸出包
• 片段,提供它們的內(nèi)容和定義到宿主bundle。
Before a bundle is resolved, all its Fragments must be attached. The
resolving process is then a constraint-solving algorithm that can be
described in terms of requirements on wiring relations. The resolving
process is an iterative process that searches through the solution
space.
If a module has both import and export definitions for the same
package, then the Framework needs to decide which to choose. It must
first try to resolve the overlapping import definition. The following
outcomes are possible:
• External – If this resolves to an export statement in another bundle,
then the overlapping export definition in this bundle is discarded.
• Internal – If it is resolved to an export statement in this module,
then the overlapping import definition in this module is discarded.
• Unresolved – There is no matching export definition. This is however
a developer error because it means the overlapping export definition of
the bundle is not compatible with the overlapping import definition.
bundle被解析之前,它所有的片段必須被附加上。這時(shí)解析過程則是一個(gè)根據(jù)連接關(guān)系需求描述成的解析約束法則。解析過程是個(gè)搜索溶解空間的交互過程。
如果一個(gè)模塊對(duì)同一個(gè)包都有引入和輸出定義,框架需要決定選擇哪一個(gè)定義,必須首先嘗試解析多重引入定義。可能會(huì)有以下結(jié)果:
• External – 如果將其解析到(選擇)另一個(gè)bundle的輸出聲明,那么這個(gè)bundle的多重輸出聲明將被放棄。
• Internal – 如果他被解析到(選擇)當(dāng)前bundle的輸出定義,那么這個(gè)多重引入定義被放棄。
• Unresolved – 沒有匹配的輸出定義。這是開發(fā)者的錯(cuò)誤,因?yàn)樗硎具@個(gè)bundle的多重輸出定義與多重引入定義不一致(同一個(gè)模塊下,一個(gè)包的引入定義找不到本模塊聲明的輸出定義)。
A bundle can be resolved if the following conditions are met:
• All its mandatory imports are wired
• All its mandatory required bundles are available and their exports
wired A wire is only created when the following conditions are met:
• The importer’s version range matches the exporter’s version. See Version Matching on page 41.
• The importer specifies all mandatory attributes from the exporter. See Mandatory Attributes on page 45.
• All the importer’s attributes match the attributes of the corresponding exporter. See Attribute Matching on page 45
• Implied packages referring to the same package as the wire are wired to the same exporter. See Package Constraints on page 43.
• The wire is connected to a valid exporter.
The following list defines the preferences, if multiple choices are possible, in order of decreasing priority:
• A resolved exporter must be preferred over an unresolved exporter.
• An exporter with a higher version is preferred over an exporter with a lower version.
• An exporter with a lower bundle ID is preferred over a bundle with a higher ID.
如果滿足以下條件,一個(gè)bundle會(huì)被解析:
• 它所有的強(qiáng)制引入被連接
• 它的強(qiáng)制需求bundles都可用,并且這些bundles的輸出連接A的連接當(dāng)滿足以下條件時(shí)被創(chuàng)建:
• 引入者的版本范圍匹配輸出者的版本
• 引入者指定了所有輸出定義的強(qiáng)制屬性
• 所有引入者的屬性匹配相應(yīng)的輸出者的屬性
• 暗指包引用同一個(gè)包,連接被連接到同一個(gè)輸出者。
• 連接被連接到可用的輸出者
如果多個(gè)選擇可用時(shí),下面的列表定義了優(yōu)先權(quán),優(yōu)先權(quán)順序遞減
• 一個(gè)解析的輸出者必須優(yōu)先于未解析輸出者
• 一個(gè)版本高的輸出者優(yōu)先于低版本
• 低ID的bundle優(yōu)先于高ID的bundle
3.8 Runtime Class Loading
Each bundle installed in the Framework must not have an associated
class loader until after it is resolved. After a bundle is resolved,
the Framework must create one class loader for each bundle that is not
a fragment. The framework may delay creation of the class loader until
it is actually needed.
One class loader per bundle allows all resources within a bundle to
have package level access to all other resources in the bundle within
the same package. This class loader provides each bundle with its own
name space, to avoid name conflicts, and allows resource sharing with
other bundles.
This class loader must use the wiring as calculated in the resolving
process to find the appropriate exporters. If a class is not found in
the imports, additional headers in the manifest can control the
searching of classes and resources in additional places.
The following sections define the factors that influence the runtime class loading and then define the exact search
安裝在框架中的每一個(gè)bundle必須不能有一個(gè)關(guān)聯(lián)的class
loader,直到這個(gè)bundle被解析之后。一個(gè)bundle被解析之后,框架必須為每一個(gè)bundle創(chuàng)建一個(gè)class
loader,而不是片段。框架可能會(huì)延遲class loader的生成,直到它真正被需要。
一個(gè)bundle的class
loader允許這個(gè)bundle中所有的資源得到對(duì)其他所有這個(gè)bundle中同一個(gè)package中的資源的包級(jí)別訪問權(quán)限。這個(gè)class
loader為bundle提供它自己的名字空間,用于避免名字沖突,允許資源共享到其他bundles。
class loader必須使用與在解析過程中一樣的連接去查找合適的輸出者。如果一個(gè)類在引入者中找不到,manifest中附加的頭可以控制在附加的空間中對(duì)類和資源的查找。
一下章節(jié)定義了影響運(yùn)行時(shí)類加載的因素,然后定義了精確查找
3.8.1 Bundle Class Path
Intra bundle class path dependencies are declared in the
Bundle-Classpath manifest header. This declaration allows a bundle to
declare its embedded class path using one or more JAR files or
directories that are contained in the bundle’s JAR file.
The Bundle-Classpath manifest header is a list of comma-separated file names. A file name can be either:
• The dot (’.’ \u002E), representing the bundle’s JAR file itself, is the default value if no Bundle-Classpath is specified.
• A path to a JAR file contained in the bundle’s JAR file.
• A path to a directory contained in the bundle’s JAR file.
The Bundle-Classpath manifest header must conform to the following syntax:
bundle內(nèi)部的類路徑依賴關(guān)系被聲明在manifest頭Bundle-Classpath中。這個(gè)聲明允許一個(gè)bundle使用一個(gè)或多個(gè)包含在bundle的JAR文件中的JAR文件或目錄去聲明它的內(nèi)部的類路徑。
頭Bundle-Classpath是一個(gè)逗號(hào)分隔的文件名列表。一個(gè)文件名可以是以下內(nèi)容:
• 點(diǎn),描述bundle的JAR文件自己,默認(rèn)值。
• 包含在bundle的JAR文件中的一個(gè)JAR文件路徑
• 包含在bundle的JAR文件中的一個(gè)目錄的路徑
頭Bundle-Classpath必須符合下面的語(yǔ)法:
Bundle-Classpath::= entry ( ’,’ entry )*
entry ::= target ( ’;’ target )*
( ’;’ parameter ) *
target ::= path | ’.’ // See 1.3.2
The Framework must ignore any unrecognized parameters.
The Framework must ignore a target in the Bundle-Classpath header if
the target (directory or JAR file) cannot be located when it is needed,
which can happen at any time after the bundle is resolved. However, in
this case the Framework should publish a Framework Event of type INFO
with an appropriate message for each entry that cannot be located.
When locating a class path entry in a bundle, the Framework must
attempt to locate the class path entry relative to the root of the
bundle’s JAR. If a class path entry cannot be located in the bundle,
then the Framework must attempt to locate the class path entry in each
of the attached fragment bundles.
The attached fragment bundles are searched in ascending bundle ID
order. This allows a fragment to supply entries that are inserted into
the host's Bundle-Classpath
The following example illustrates this:
框架必須忽略所有未經(jīng)承認(rèn)的參數(shù)。
框架必須忽略頭Bundle-Classpath中的target,如果當(dāng)需要的時(shí)候這個(gè)target(目錄或JAR文件)不能被找到,這個(gè)忽略可以發(fā)生
在bundle被解析后的任何時(shí)間。盡管如此,在這種情況下,框架應(yīng)該發(fā)布一個(gè)類型為INFO的事件,為每一個(gè)不能定位的entry生成一條合適的消息。
當(dāng)在bundle中定位一個(gè)類路徑實(shí)體的時(shí)候,框架必須嘗試定位相對(duì)于bundle的JAR文件的根路徑的類路徑實(shí)體。如果在bundle一個(gè)類路徑不能被定位,那么框架必須嘗試定位每一個(gè)附加片段bundles中的類路徑實(shí)體。
附加片段bundles通過bundle ID的升序來(lái)查找。這就允許了片段提供宿主bundle的頭Bundle-Classpath中插入的實(shí)體。
請(qǐng)看下面是個(gè)例子:
A: Bundle-SymbolicName: A
Bundle-Classpath: required.jar,optional.jar,default.jar
content 
required.jar
default.jar
B: Bundle-SymbolicName: B
Bundle-Classpath: fragment.jar
Fragment-Host: A
content 
optional.jar
fragment.jar
In this example, bundle A has a Bundle-Classpath header with three
entries (required.jar, optional.jar, and default.jar). The required.jar
class path entry may contain the classes and resources that must be
present for the bundle to function. The optional.jar class path entry
may contain classes and resources that the bundle will use if present.
The default.jar class path entry may contain classes and resources that
the bundle will use if the optional.jar is not available, but the
classes and resources from default.jar can be overridden by classes and
resources in the optional.jar (from the fragment) class path entries.
Bundle A has only the required.jar and default.jar entries packaged
with it. This allows a fragment bundle B to be installed that can
supply the optional.jar for bundle A.
The fragment bundle B has a Bundle-Classpath with one entry (fragment.
jar). When bundle A is resolved and the fragment bundle B is attached
then the bundle class path for the bundle A is:
在這個(gè)例子中,bundle A的頭Bundle-Classpath有3個(gè)實(shí)體(required.jar, optional.jar, and
default.jar)。required.jar類路徑實(shí)體可能包含必須提供給bundle的功能的類和資源。optional.jar類路徑實(shí)體可
能包含如果提供,bundle會(huì)使用到的類和資源(例如logging)。
default.jar類路徑實(shí)體可能包含如果optional.jar不可用,那么bundle可能會(huì)用到的類和資源,但是default.jar中的
類和資源能被optional.jar(片段bundle中)中的類和資源重載。bundle
A中只打包了required.jar和default.jar實(shí)體,這允許片段bundle B被安裝,為bundle
A提供optional.jar。
片段bundle B頭Bundle-Classpath有一個(gè)實(shí)體(fragment. jar)。當(dāng)bundle A被解析,片段bundle B被附加時(shí),bundle A的類路徑則成為:
required.jar, optional.jar, default.jar, fragment.jar
3.8.2 Dynamic Import Package
Dynamic imports are matched to export definitions (to form package
wirings) during class loading, and therefore do not affect module
resolution.
Dynamic imports apply only to packages for which no wire has been
established and no definition could be found in any other way. Dynamic
import is used as last resort.
動(dòng)態(tài)引入在類加載期間被匹配到輸出定義(用于構(gòu)成包連接),因此不會(huì)影響到模塊的解析。
動(dòng)態(tài)引入僅僅適用于沒有被連接和無(wú)法從其他方式獲得定義的包。動(dòng)態(tài)引入是最后的手段。
DynamicImport-Package ::= dynamic-description
( ',' dynamic-description )*
dynamic-description::= wildcard-names ( ';' parameter )*
wildcard-names ::= wildcard-name ( ';' wildcard-name )*
wildcard-name ::= package-name
| ( package-name '.*' ) // See 1.3.2
| '*'
No directives are architected by the Framework for DynamicImport-Package.
Arbitrary matching attributes may be specified. The following arbitrary matching attributes are architected by the Framework:
• version -- A version range to select the version of an export definition. The default value is 0.0.0 .
• bundle-symbolic-name – The bundle symbolic name of the exporting bundle.
• bundle-version – a version range to select the bundle version of the exporting bundle. The default value is 0.0.0.
Packages may be named explicitly or by using wild-carded expressions
such as org.foo.* and *. The wildcard can stand for any suffix,
including multiple sub-packages.
Dynamic imports must be searched in the order in which they are specified.
The order is particularly important when package names with wildcards
are used. The order will then determine the order in which matching
occurs.
This means that the more specific package specifications should appear
before the broader specifications. For example, the following
DynamicImport- Package header indicates a preference for packages
supplied by ACME:
框架不必為DynamicImport-Package創(chuàng)建指令,可以指定專有匹配屬性,一下專有匹配屬性由框架給定:
• version -- 一個(gè)版本范圍,用于選擇輸出定義的版本。默認(rèn)值是0.0.0
• bundle-symbolic-name – 輸出bundle的標(biāo)記名
• bundle-version – 一個(gè)版本范圍,用于選擇輸出bundle的版本。默認(rèn)值是0.0.0
packages能被明確指定,或使用通配符表達(dá)式,它能代替任何后綴,包括多個(gè)sub-packages。
動(dòng)態(tài)引入必須在指定的順序下查找包。
當(dāng)包名使用的是通配符時(shí),這個(gè)順序顯得尤為重要。這時(shí),這個(gè)順序?qū)Q定發(fā)生匹配的順序。
也就是說指定的包規(guī)范應(yīng)該更多的出現(xiàn)在擴(kuò)展規(guī)范之前。例如,下面這個(gè)頭DynamicImport- Package表示優(yōu)先選擇由ACME提供的包
DynamicImport-Package: *;vendor=acme, *
If multiple packages need to be dynamically imported with identical
parameters, the syntax permits a list of packages, separated by
semicolons, to be specified before the parameters.
During class loading, the package of the class being loaded is compared
against the specified list of (possibly wild-carded) package names.
Each matching package name is used in turn to attempt to wire to an
export using the same rules as Import-Package. If a wiring attempt is
successful (taking any uses constraints into account), the search is
forwarded to the exporter’s class loader where class loading continues.
The wiring must not subsequently be modified, even if the class cannot
be loaded. This implies that once a package is dynamically resolved,
subsequent attempts to load classes or resources from that package are
treated as normal imports.
如果多個(gè)包需要被以相同的參數(shù)引入,這個(gè)語(yǔ)法允許一個(gè)包列表,以分號(hào)隔開,指定在參數(shù)之前。
類加載期間,被加載的類的包被與指定的包名的列表(或通配符)比較,每一個(gè)匹配的包名輪流嘗試按照Import-Package的規(guī)則連接到一個(gè)輸出。如
果一個(gè)嘗試連接成功(按照uses約束),當(dāng)繼續(xù)加載類時(shí),查找會(huì)被定位到輸出者的class
loader。之后,這個(gè)連接必須不能被更改,即使隨后的類不能被加載。也就是說一旦一個(gè)包是被動(dòng)態(tài)解析的,那么隨后嘗試從這個(gè)包中加載類或資源將被視為
普通引入。
In order for a DynamicImport-Package to be resolved to an export
statement, all attributes of the dynamic import definition must match
the attributes of the export statement. All mandatory arbitrary
attributes (as specified by the exporter, see Mandatory Attributes on
page 45) must be specified in the dynamic import definition and match.
Once a wire is established, any uses constraints from the exporter must be obeyed for further dynamic imports.
Dynamic imports are very similar to optional packages, see Optional
Packages on page 42, but differ in the fact that they are handled after
the bundle is resolved.
為了使一個(gè)動(dòng)態(tài)引入包被解析到一個(gè)輸出聲明,所有動(dòng)態(tài)引入定義中的屬性必須匹配輸出聲明中的屬性,所有輸出聲明中的強(qiáng)制專有屬性必須在動(dòng)態(tài)引入定義中指定并匹配。
一旦一個(gè)連接被產(chǎn)生,輸出者中所有uses約束必須被動(dòng)態(tài)引入者遵循。
動(dòng)態(tài)引入與可選包非常相似,但是實(shí)際上他們區(qū)別于bundle被解析之后才被處理。
3.8.3 Parent Delegation
The Framework must always delegate any package that starts with java. to the parent class loader.
Certain Java virtual machines, also SUN’s VMs, appear to make the
erroneous assumption that the delegation to the parent class loader
always occurs. This implicit assumption of strictly hierarchical class
loader delegation can result in NoClassDefFoundErrors. This happens if
the virtual machine implementation expects to find its own
implementation classes from any arbitrary class loader, requiring that
packages loaded from the boot class loader not be restricted to only
the java.* packages.
Other packages that must be loaded from the boot class loader can therefore be specified with the System property:
框架必須總是代理以java開頭的包到parent class cloader。
顯然JVM做了一個(gè)錯(cuò)誤的假設(shè),到parent class cloader的代理總是會(huì)發(fā)生。而這個(gè)嚴(yán)格等級(jí)的class
loader代理的所隱藏的假設(shè),會(huì)導(dǎo)致NoClassDefFoundErrors。如果虛擬機(jī)實(shí)現(xiàn)希望從所有專有class
loader中查找它自己的實(shí)現(xiàn)類,它需要的包是從boot class loader中加載的,而不僅僅局限于java.*這樣的包。
因此,其他必須從boot class loader加載的包能被指定到以下系統(tǒng)屬性:
org.osgi.framework.bootdelegation
This property must contain a list with the following format:
org.osgi.framework.bootdelegation ::= boot-description
( ',' boot-description )*
boot-description::= package-name // See 1.3.2
| ( package-name '.*' )
| '*'
The .* wildcard means deep matching. Packages that match this list must
be loaded from the parent class loader. The java.* prefix is always
implied; it does not have to be specified.
The single wildcard means that the Framework must always delegate to
the parent class loader first, which is the same as the Release 3
behavior. For example, when running on a SUN JVM, it may be necessary
to specify a value like:
通配符.*表示深層匹配。匹配這個(gè)列表的包必須被從parent class
loader中加載。前綴java.*總是隱含著;而不需要指定。單個(gè)通配符表示框架必須總是首先代理到parent class
loader,與版本3一樣。例如,當(dāng)運(yùn)行于sun jvm時(shí),它可能有必要指定一個(gè)如下的值:
org.osgi.framework.bootdelegation=sun.*,com.sun.*
With such a property value, the Framework must delegate all java.*, sun.*, and com.sun.* packages to the parent class loader.
對(duì)于這樣的值,框架必須代理所有java.*, sun.*, 和 com.sun.*的包到parent class loader。
3.8.4 Overall Search Order
Frameworks must adhere to the
following rules for class or resource loading. When a bundle’s class
loader is requested to load a class or find a resource, the search must
be performed in the following order:
框架必須遵循以下規(guī)則來(lái)加載類或資源。當(dāng)一個(gè)bundle的class loader被請(qǐng)求加載類或查找資源時(shí),必須按照以下順序來(lái)執(zhí)行:
1 If the class or resource is in a java.* package, the request is
delegated to the parent class loader; otherwise, the search continues
with the next step. If the request is delegated to the parent class
loader and the class or resource is not found, then the search
terminates and the request fails.
1. 如果類或資源在一個(gè)java.*的包中,這個(gè)請(qǐng)求被代理到parent class loader,否則,進(jìn)入下一步。如果請(qǐng)求被代理到parent class loader,而類或資源卻沒有找到,那么查找被中斷,請(qǐng)求失敗。
2 If the class or resource is from a package included in the boot
delegation list (org.osgi.framework.bootdelegation), then the request
is delegated to the parent class loader. If the class or resource is
found there, the search ends.
2. 如果類或資源來(lái)自一個(gè)包含在boot代理列表中的包,那么這個(gè)請(qǐng)求被代理到parent class loader。如果類或資源被找到,那么請(qǐng)求結(jié)束。
3 If the class or resource is in a package that is imported using
Import-Package or was imported dynamically in a previous load, then the
request is delegated to the exporting bundle’s class loader; otherwise
the search continues with the next step. If the request is delegated to
an exporting class loader and the class or resource is not found, then
the search terminates and the request fails.
3. 如果類或資源是在一個(gè)使用Import-Package引入,或是前面的加載中動(dòng)態(tài)引入的包中,那么請(qǐng)求將被代理到輸出bundle的class
loader。否則進(jìn)入下一步。如果請(qǐng)求被代理到一個(gè)輸出bundle的class loader,類或資源沒有找到,那么查找中斷,請(qǐng)求失敗。
4 If the class or resource is in a package that is imported from one or
more other bundles using Require-Bundle, the request is delegated to
the class loaders of the other bundles, in the order in which they are
specified in this bundle’s manifest. This entails a depth-first
strategy; all required bundles are searched before the bundle classpath
is used. If the class or resource is not found, then the search
continues with the next step.
4.
如果類或資源是在一個(gè)使用Require-Bundle從一個(gè)或多個(gè)其他bundles引入的包中,這個(gè)請(qǐng)求將被代理到這些bundles的class
loader,按照manifest中指定的順序。這確保了深度優(yōu)先策略;所有required
bundles在bundle類路徑使用之前被查找。如果類或資源沒有找到,進(jìn)入下一步。
5 The bundle’s own internal bundle class path is searched. If the class
or resource is not found, then the search continues with the next step.
5. 查找bundle自己的內(nèi)部類路徑。如果資源或類沒有找到,進(jìn)入下一步。
6 Each attached fragment’s internal bundle class path is searched. The
fragments are searched in ascending bundle ID order. If the class or
resource is not found, then the search continues with the next step.
6. 查找附加片段的內(nèi)部bundle類路徑,查找順序根據(jù)bundle ID的升序,如果沒有找到,進(jìn)入下一步。
7 If the class or resource is in a package that is exported by the
bundle or the package is imported by the bundle (using Import-Package
or Require-Bundle), then the search ends and the class or resource is
not found.
7. 如果類或資源是在一個(gè)被片段bundle輸出的包中,或者這個(gè)包被片段bundle(使用Import-Package or Require-Bundle)引入,那么查找終止,類或資源無(wú)法被找到。
8 Otherwise, if the class or resource is in a package that is imported
using DynamicImport-Package, then a dynamic import of the package is
now attempted. An exporter must conform to any implied package
constraints. If an appropriate exporter is found, a wire is established
so that future loads of the package are handled in Step 3. If a dynamic
wire is not established, then the request fails.
8.
否則,如果類或資源是在一個(gè)使用DynamicImport-Package引入的包中,那么包的動(dòng)態(tài)引入被附加。一個(gè)輸出者必須遵循所有的暗指包約束。
如果一個(gè)合適的輸出者被找到,一個(gè)連接被創(chuàng)建,然后包的加載在步驟3中被處理。如果一個(gè)動(dòng)態(tài)連接沒有被創(chuàng)建,那么請(qǐng)求失敗。
9 If the dynamic import of the package is established, the request is
delegated to the exporting bundle’s class loader. If the request is
delegated to an exporting class loader and the class or resource is not
found, then the search terminates and the request fails.
9. 如果包的動(dòng)態(tài)引入被創(chuàng)建,請(qǐng)求被代理到輸出bundle(片段bundle)的class loader。如果類或資源沒有找到,查找失敗。
When delegating to another bundle class loader, the delegated request enters this algorithm at Step 4.
The following non-normative flow chart illustrates the search order described above:
3.8.5 Parent Class Loader
The set of implicitly imported packages are all java.* packages, since
these packages are required by the Java runtime, and using multiple
versions at the same time is not easy. For example, all objects must
extend the same Object class.
A bundle must not declare imports or exports for java.* packages; doing
so is an error and any such bundle must fail to install. All other
packages available through the parent class loader must be hidden from
executing bundles.
However, the Framework must explicitly export relevant packages from the parent class loader.
The system property
暗指包是所有java.*包,因?yàn)檫@些包是JAVA運(yùn)行所需。在同一時(shí)間使用多個(gè)版本并不容易,例如,所有的對(duì)象必須繼承同一個(gè)類Object
一個(gè)bundle必須不能為包java.*聲明輸出或引入;這么做是一個(gè)錯(cuò)誤并且凡是這樣做的bundle都必須安裝失敗。所有其他對(duì)parent class loader可用的包必須被隱藏到執(zhí)行bundles。
可是,框架必須輸出parent class loader相關(guān)的包。
系統(tǒng)屬性
org.osgi.framework.system.packages
contains the export packages descriptions for the system bundle. This
property employs the standard Export-Package manifest header syntax:
包含了描述系統(tǒng)bundle的輸出包。它使用標(biāo)準(zhǔn)Export-Package頭語(yǔ)法
org.osgi.framework.system.packages ::= package-description (
',' package-description )*
Some classes on the boot class path assume that they can use any class
loader to load other classes on the boot class path, which is not true
for a bundle class loader. Framework implementations should attempt to
load these classes from the boot class path.
The system bundle (bundle ID zero) is used to export non-java.*
packages from the parent class loader. Export definitions from the
system bundle are treated like normal exports, meaning that they can
have version numbers, and are used to resolve import definitions as
part of the normal bundle resolving process. Other bundles may provide
alternative implementations of the same packages.
The set of export definitions for the parent class loader can either be
set by this property or calculated by the Framework. The export
definitions must have the implementation specific bundle symbolic name
and version value of the system bundle.
Exposing packages from the parent class loader in this fashion must
also take into account any uses directives of the underlying packages.
For example, the definition of javax.crypto.spec must declare its usage
of
javax.crypto.interfaces and javax.crypto.
一些boot class path中的類假設(shè)為他們可以使用任何class loader去加載boot class path中的其他類,對(duì)于一個(gè)bundle的class loader這時(shí)不對(duì)的??蚣軕?yīng)該嘗試從boot class path加載這些類。
系統(tǒng)bundle(ID是0)用于從parent class
loader中輸出非java.*的包。系統(tǒng)bundle中的輸出定義被視為常規(guī)輸出,也就是說它們能有版本號(hào),用于解析引入定義,作為常規(guī)解析的一部
分。其他bundles可以提供對(duì)同一個(gè)包作為選擇的實(shí)現(xiàn)。
parent class loader的輸出定義能被這個(gè)屬性設(shè)置或是通過框架決定。輸出定義必須有實(shí)現(xiàn)系統(tǒng)bundle的特定bundle標(biāo)記名和版本號(hào)。
通過這個(gè)方式從parent class loader中暴露(輸出)的包必須考慮到這些包的uses指令。例如,javax.crypto.spec的定義必須聲明它的
javax.crypto.interfaces 和 javax.crypto.的用法
3.8.6 Resource Loading
A resource in a bundle can be accessed through the class loader of that
bundle but it can also be accessed with the getResource, getEntry or
findEntries methods. All these methods return a URL object or an
Enumeration object of URL objects. The URLs are called bundle entry
URLs. The schemes for the URLs returned by these methods can differ and
are implementation dependent.
Bundle entry URLs are normally created by the Framework, however, in
certain cases bundles need to manipulate the URL to find related
resources. The Framework is therefore required to ensure that:
一個(gè)bundle中的資源可以通過這個(gè)bundle的class loader,它同樣能被方法getResource, getEntry 或
findEntries訪問到。所有這些方法都返回一個(gè)URL對(duì)象或一個(gè)URL對(duì)象的Enumeration對(duì)象。URLs
被稱為bundle實(shí)體URLs。
bundle實(shí)體URLs通常是由框架生成,但是無(wú)論如何都是通過操作URL找到相關(guān)資源。因此框架需要確保:
• Bundle entry URLs must be hierarchical (See [32] Uniform Resource Identifiers URI: Generic Syntax)
• Usable as a context for constructing another URL.
• The java.net.URLStreamHandler class used for a bundle entry URL must
be available to the java.net.URL class to setup a URL that uses the
protocol scheme defined by the Framework.
• The getPath method for a bundle entry URL must return an absolute
path (a path that starts with '/') to a resource or entry in a bundle.
For example, the URL returned from getEntry("myimages/test.gif") must
have a path of /myimages/test.gif.
• bundle實(shí)體URLs必須是分等級(jí)的。
• 對(duì)構(gòu)造其他URL的context可用。
• 使用于bundle entry URL的類java.net.URLStreamHandler必須對(duì)類java.net.URL可用,用于設(shè)置一個(gè)使用框架定義的協(xié)議摘要的URL。
• 用于一個(gè)bundle entry URL的方法getPath必須返回一個(gè)bundle中的資源或?qū)嶓w的絕對(duì)路徑,
For example, a class can take a URL to an index.html bundle resource
and map URLs in this resource to other files in the same JAR directory.
public class BundleResource implements HttpContext {
URL root; // to index.html in bundle
URL getResource( String resource ) {
return new URL( root, resource );
}

}
3.8.7 Bundle Cycles
Multiple required bundles can export the same package. Bundles which
export the same package involved in a require bundle cycle can lead to
lookup cycles when searching for classes and resources from the package.
Consider the following definitions:
多個(gè)必須的bundle能輸出同一個(gè)包。輸出同一個(gè)包的bundles包含了一個(gè)bundle循環(huán),能循環(huán)查找包中的類和資源。
考慮下面的定義
A: Require-Bundle: B, C
C: Require-Bundle: D
These definitions are depicted in Figure 3.19.

Each of the bundles exports the package p. In this example, bundle A
requires bundle B, and bundle C requires bundle D. When bundle A loads
a class or resource from package p, then the required bundle search
order is the following: B, D, C, A. This is a depth first search order
because required bundles are searched before the bundle classpath is
searched (see step 4).
The required bundles are searched in the order that they appear in the
Require-Bundle header. The depth first search order can introduce
endless search cycles if the dependency graph has a cycle in it.
Using the previous setup, a cycle can be introduced if bundle D requires bundle A as depicted in Figure 3.20.
他們都輸出包p。在這個(gè)例子中,bundle A需要bundle B,和C,bundle C需要bundle D.當(dāng)bundle
A從包p中加載一個(gè)類或資源時(shí),查找順序則為:B,D,C,A. 這時(shí)一個(gè)深層有限查找順序,因?yàn)閞equired
bundles先于本bundle的classpath被查找。
required bundles被查找的順序按照Require-Bundle頭中出現(xiàn)的順序。深層有限查找順序能陷入無(wú)限查找循環(huán),如果里面的依賴圖是循環(huán)的話。
D: Require-Bundle: A

When the class loader for bundle A loads a class or resource from
package p then the bundle search order would be the following: B, B,
B,... if cycles were not taken into account.
Since a cycle was introduced each time bundle D is reached the search
will recurs back to A and start over. The framework must prevent such
dependency cycles from causing endless recursive lookups.
To avoid endless looping, the Framework must mark each bundle upon
first visiting it and not explore the required bundles of a previously
visited bundle. Using the visited pattern on the dependency graph above
will result in the following bundle search order: B, D, C, A.
當(dāng)bundle A的class loader從包p加載一個(gè)類或資源時(shí),bundle查找順序?qū)⒆兂桑築,B,B,...如果不考慮循環(huán)。
因?yàn)槊看窝h(huán)到bundle D的時(shí)候,查找將會(huì)返回到A并重新開始??蚣鼙仨毞乐惯@種依賴循環(huán)導(dǎo)致的無(wú)限遞歸查找。
要避免無(wú)限循環(huán),框架必須標(biāo)記每個(gè)bundle第一次訪問,并且不會(huì)訪問先前訪問過的bundle的required bundles。 將這個(gè)模式使用在上面的依賴圖中,將是查找順序變?yōu)椋築,D,C,A.
3.8.8 Code Executed Before Started
Packages exported from a bundle are exposed to other bundles as soon as
the bundle has been resolved. This condition could mean that another
bundle could call methods in an exported package before the bundle
exporting the package is started.
一旦一個(gè)bundle被解析,它輸出的包將暴露給其他bundles。也就是說輸出了包的bundle啟動(dòng)之前,其他bundle就能調(diào)用這個(gè)包中的方法了。
3.9 Loading Native Code Libraries
When a class loaded by a bundle's class loader attempts to load a
native library, by calling System.loadLibrary, the findLibrary method
of the bundle’s class loader must be called to return the file path in
which the Framework has made the requested native library available.
The parameter to the findLibrary method is the name of the library in
operating system independent form, like http. The bundle class loader
can use the mapLibraryName method from the VM to map this name to an
operating system dependent name, like libhttp.so.
當(dāng)一個(gè)被bundle的class loader加載了的類嘗試使用System.loadLibrary加載本地庫(kù)時(shí),bundle的class
loader的findLibrary方法必須被調(diào)用,用于返回文件路徑,框架已經(jīng)使其可用。findLibrary方法的參數(shù)是操作系統(tǒng)中獨(dú)立庫(kù)的名
字,例如http。這個(gè)bundle的class
loader可以使用VM的方法mapLibraryName將這個(gè)名字映射到由操作系統(tǒng)決定的名字,就像libhttp.so。
The bundle's class loader must attempt to find the native library by
examining the selected native code clauses, if any, of the bundle
associated with the class loader and each attached fragment. Fragments
are examined in ascending bundle ID order. If the library is not
referenced in any of the selected native code clauses then null must be
returned which allows the parent class loader to search for the native
library.
The bundle must have the required
RuntimePermission[loadLibrary.<library name>] in order to load
native code in the OSGi Service Platform.
The Bundle-NativeCode manifest header must conform to the following syntax:
Bundle-NativeCode ::= nativecode
( ',' nativecode )* ( ’,’ optional) ?
nativecode ::= path ( ';' path )* // See 1.3.2
( ';' parameter )+
optional ::= ’*’
When locating a path in a bundle the Framework must attempt to locate
the path relative to the root of the bundle that contains the
corresponding native code clause in its manifest header.
The following attributes are architected:
• osname – Name of the operating system. The value of this attribute
must be the name of the operating system upon which the native
libraries run. A number of canonical names are defined in Environment
Properties on page 93.
• osversion – The operating system version. The value of this attribute
must be a version range as defined in Version Ranges on page 28.
• processor – The processor architecture. The value of this attribute
must be the name of the processor architecture upon which the native
libraries run. see Environment Properties on page 93.
• language – The ISO code for a language. The value of this attribute
must be the name of the language for which the native libraries have
been localized.
• selection-filter – A selection filter. The value of this attribute
must be a filter expression that indicates if the native code clause
should be selected or not.
The following is a typical example of a native code declaration in a bundle's manifest:
Bundle-NativeCode: lib/http.dll ; lib/zlib.dll ;
osname = Windows95 ;
osname = Windows98 ;
osname = WindowsNT ;
processor = x86 ;
selection-filter=
"(com.acme.windowing=win32)";
language = en ;
language = se ,
lib/solaris/libhttp.so ;
osname = Solaris ;
osname = SunOS ;
3.10 Localization
A bundle contains a significant amount of information that is
human-readable. Some of this information may require different
translations depending on the user's language, country, and any special
variant preferences, a.k.a. the locale. This section describes how a
bundle can provide common translations for the manifest and other
configuration resources depending on a locale.
Bundle localization entries share a common base name. To find a
potential localization entry, an underscore (’_’ \u005F) is added plus
a number of suffixes, separated by another underscore, and finally
appended with the suffix .properties . The suffixes are defined in
java.util.Locale.
The order for the suffixes this must be:
• language
• country
• variant
For example, the following files provide manifest translations for English, Dutch (Belgium and the Netherlands) and Swedish.
一個(gè)bundle包含一個(gè)長(zhǎng)幅的可讀性信息。這些信息可能需要根據(jù)用戶語(yǔ)言,國(guó)家和任何指定的變量參數(shù)(也叫做locale)的不同來(lái)進(jìn)行轉(zhuǎn)換。本節(jié)描述了一個(gè)bundle怎樣根據(jù)一個(gè)locale來(lái)提供一個(gè)普通的轉(zhuǎn)換給manifest和其他配置資源。
bundle本地化實(shí)體共享一個(gè)基本的普通名字。要找到潛在的本地化實(shí)體,會(huì)有一個(gè)下劃線加上一個(gè)后綴,由另一個(gè)下劃線分隔,最終以后綴.properties結(jié)束。這個(gè)后綴定義在java.util.Locale。
OSGI-INF/l10n/bundle_en.properties
OSGI-INF/l10n/bundle_nl_BE.properties
OSGI-INF/l10n/bundle_nl_NL.properties
OSGI-INF/l10n/bundle_sv.properties
The Framework searches for localization entries by appending suffixes
to the localization base name according to a specified locale and
finally appending the .properties suffix. If a translation is not
found, the locale must be made more generic by first removing the
variant, then the country and finally the language until an entry is
found that contains a valid translation.
框架查找本地化實(shí)體,通過根據(jù)指定的locale 添加后綴到本地化基礎(chǔ)名,最后添加后綴.properties。如果一個(gè)轉(zhuǎn)換沒有找到,locale必須通過刪除第一個(gè)變量,接著是國(guó)家,最后是語(yǔ)言,從而變得更通用,直到一個(gè)包含了可用轉(zhuǎn)換的實(shí)體被發(fā)現(xiàn)。
For example, looking up a translation for the locale en_GB_welsh will search in the following order:
例如,查找順序如下:
OSGI-INF/l10n/bundle_en_GB_welsh.properties
OSGI-INF/l10n/bundle_en_GB.properties
OSGI-INF/l10n/bundle_en.properties
OSGI-INF/l10n/bundle.properties
This allows localization files for more specific locales to override localizations from less specific localization files.
3.10.1 Finding Localization Entries
Localization entries can be contained in the bundle or delivered in
fragments. The Framework must therefore first look in the bundle and
then in its attached fragments. Fragment bundles must delegate the
search for a localization entry to their host bundle with the lowest
bundle ID.
The bundle's class loader is not used to search for localization
entries. Only the contents of the bundle and its attached fragments are
searched. The bundle will still be searched for localization entries
even if dot ('.') is not in the bundle class path.
本地化實(shí)體可以被包含在bundle中,或放在片段中。因此框架必須首先查看bundle,然后再看它的片段。片段bundle必須代理它的最小ID的宿主bundle對(duì)本地化實(shí)體的查找。
bundle的class loader不是用來(lái)查找本地化實(shí)體的。僅僅是bundle的內(nèi)容和它的片段被查找。即使.不在bundle的類路徑中,bundle將仍然會(huì)被查找本地化實(shí)體。
3.10.2 Manifest Localization
Localized values are stored in property resources within the bundle.
The default base name of the bundle localization property files is
OSGI-INF/l10n/bundle. The Bundle-Localization manifest header can be
used to override the default base name for the localization files. This
location is relative to the root of the bundle and bundle fragments.
A localization entry contains key/value entries for localized
information. All headers in a bundle's manifest can be localized.
However, the Framework must always use the non-localized versions of
headers that have Framework semantics.
A localization key can be specified as the value of a bundle's manifest header using the following syntax:
本地值被保存在bundle中的屬性資源中。bundle本地化屬性文件的默認(rèn)基礎(chǔ)名是OSGI-INF/l10n/bundle。頭Bundle-Localization用于重載這個(gè)默認(rèn)值,路徑是相對(duì)于bundle和片段bundle的根路徑。
一個(gè)本地化實(shí)體包含用于本地信息的key/value實(shí)體。manifest中所有的頭都能被本地化。然而,框架必須始終使用含有框架語(yǔ)義的頭的非本地化版本。
使用以下語(yǔ)法指定manifest頭中的本地化值
header-value ::= ’%’text
text ::= < any value which is both a valid manifest header value and a valid property key name >
For example, consider the following bundle manifest entries:
Bundle-Name: %acme bundle
Bundle-Vendor: %acme corporation
Bundle-Description: %acme description
Bundle-Activator: com.acme.bundle.Activator
Acme-Defined-Header: %acme special header
User-defined headers can also be localized. Spaces in the localization keys are explicitly allowed.
用戶定義的頭也能被本地化。本地化KEY是可以包含空格的
The previous example manifest entries could be localized by the
following entries in the manifest localization entry
OSGI-INF/l10n/bundle.properties.
# bundle.properties
acme\ bundle=The ACME Bundle
acme\ corporation=The ACME Corporation
acme\ description=The ACME Bundle provides all of the ACME \services
acme\ special header=user-defined Acme Data
The above manifest entries could also have French localizations in the
manifest localization entry OSGI-INF/l10n/bundle_fr_FR.properties.
3.11 Bundle Validity
If the Bundle-ManifestVersion is not specified, then the bundle
manifest version defaults to 1, and certain Release 4 syntax, such as a
new manifest header, is ignored rather than causing an error. Release 3
bundles must be treated according to the R3 specification.
如果Bundle-ManifestVersion沒有被指定,那么將被設(shè)置成默認(rèn)值1,對(duì)于版本4的語(yǔ)法,像這種新manifest頭,將被忽略,而不是拋出錯(cuò)誤。版本3的bundle必須根據(jù)版本3規(guī)范使用。
The following (non-exhaustive) list of errors causes a bundle to fail to install:
下面的錯(cuò)誤列表會(huì)使bundle安裝失敗:
• Bundle-RequireExecutionEnvironment header does not match the available execution environments.
• 頭Bundle-RequireExecutionEnvironment不匹配可用的執(zhí)行環(huán)境
• Missing Bundle-SymbolicName.
• 缺少頭Bundle-SymbolicName
• Duplicate attribute or duplicate directive (except in the Bundle-Native code clause).
• 多個(gè)屬性或指令
• Multiple imports of a given package.
• 對(duì)一個(gè)包的多次引入
• Export or import of java.*.
• 輸出或引入java.*
• Export-Package with a mandatory attribute that is not defined.
• Export-Package的強(qiáng)制屬性是沒有定義的(3.6.6關(guān)于強(qiáng)制屬性的定義)
• Installing a bundle that has the same symbolic name and version as an already installed bundle.
• 安裝一個(gè)bundle,與已經(jīng)安裝的bundle具有相同的標(biāo)記名和版本
• Updating a bundle to a bundle that has the same symbolic name and version as another installed bundle.
• 更新一個(gè)bundle,與已經(jīng)安裝的bundle具有相同的標(biāo)記名和版本
• Any syntactic error (for example, improperly formatted version or bundle symbolic name, unrecognized directive value, etc.).
• 任何語(yǔ)法錯(cuò)誤(例如,不正確的版本和標(biāo)記名格式,無(wú)效的的指令等)
• Specification-version and version specified together (for the same
package(s)) but with different values on manifest headers that treat
them as synonyms. For example:
• 為同一個(gè)包同時(shí)指定Specification-version和version相同的值。
Import-Package p;specification-version=1;version=2
would fail to install, but:
Import-Package p;specification-version=1, q;version=2
would not be an error.
• The manifest lists a OSGI-INF/permission.perm file but no such file is present.
• manifest指定了OSGI-INF/permission.perm文件,卻沒有這個(gè)文件存在。
• Bundle-ManifestVersion value not equal to 2, unless the Framework specifically recognizes the semantics of a later release.
• Bundle-ManifestVersion的值不等于2,除非框架明確給出后面的版本的語(yǔ)義
3.12 Optional
This specification provides for one optional mechanism: the boot class
path extension. The reason to make this mechanism optional is that it
is not possible to implement this in a portable way. A compliant
framework must set the following property to true or false depending on
the implementation of the boot class path extension:
• org.osgi.supports.bootclasspath.extension
If the property is not set or the value is unrecognized, then the value
defaults to false. A Framework that does not implement the
bootclasspath extension must refuse to install or update a bundle that
carries this option. It must then throw an exception at install or
update time.
Additionally, frameworks must implement fragments, require bundle, and
extensions. They must therefore set the following properties to true.
這部分規(guī)范提供了一個(gè)可選機(jī)制:boot類路徑擴(kuò)展。將這個(gè)機(jī)制做成可選的原因是它不可能很輕易被實(shí)現(xiàn)。一個(gè)適應(yīng)性強(qiáng)的框架必須根據(jù)對(duì)boot類路徑擴(kuò)展的實(shí)現(xiàn)來(lái)設(shè)置這個(gè)屬性的值為true或false。
• org.osgi.supports.bootclasspath.extension
如果這個(gè)屬性沒有設(shè)置,或沒有賦值,那么默認(rèn)值為false。一個(gè)沒有實(shí)現(xiàn)bootclasspath extension的框架必須拒絕安裝或更新一個(gè)帶有這個(gè)選項(xiàng)的bundle。然后拋出一個(gè)exception。
另外,框架必須實(shí)現(xiàn)fragments, require bundle, and extensions。因此一下屬性必須賦值為true:
• org.osgi.supports.framework.requirebundle
• org.osgi.supports.framework.fragments
• org.osgi.supports.framework.extension
3.13 Requiring Bundles
The Framework supports a mechanism where bundles can be directly wired
to other bundles. The following sections define the relevant headers
and then discuss the possible scenarios. At the end, some of the
(sometimes unexpected) consequences of using Require-Bundle are
discussed.
框架支持bundle直接連接到另外的bundle機(jī)制。一下章節(jié)定義了相關(guān)的頭,然后討論可能的假設(shè)。最后,討論一些使用Require-Bundle的結(jié)果。
3.13.1 Require-Bundle
The Require-Bundle manifest header contains a list of bundle symbolic
names that need to be searched after the imports are searched but
before the bundle’s class path is searched. Fragment or extension
bundles can not be required. Only packages that are marked exported by
the required bundles are visible to the requiring bundle.
The Require-Bundle manifest header must conform to the following syntax:
頭Require-Bundle包含了bundle標(biāo)記名的列表,這些標(biāo)記名需要在引入查找之后,bundle類路徑查找之前被查找。片段或擴(kuò)展不是必須的。只有被 required bundles標(biāo)記為輸出的包材對(duì)requiring bundle可見。
Require-Bundle ::= bundle-description( ',' bundle-description )*
bundle-description ::= symbolic-name // See 1.3.2(';' parameter )*
The following directives can be used in the Require-Bundle header:
以下指令可以用在頭Require-Bundle中:
• visibility – If the value is private (Default), then all visible
packages from the required bundles are not re-exported. If the value is
reexport then bundles that require this bundle will transitively have
access to these required bundle’s exported packages. That is, if bundle
A requires bundle B, and bundle B requires bundle C with
visibility:=reexport then bundle A will have access to all bundle C’s
exported packages as if bundle A had required bundle C.
• visibility – 如果值是private(默認(rèn)值),那么所有required
bundles中可見的包都不會(huì)重新輸出。如果值是reexport ,那么需要這個(gè)bundle的bundles將可以訪問這些required
bundle輸出的包。也就是說,如果bundle A需要bundle B,bundle B需要bundle C,bundle
B的頭Require-Bundle 的visibility ="reexport",那么A將可以訪問C輸出的包,就像A需要C一樣。
• resolution – If the value is mandatory (default) then the required
bundle must exist for this bundle to resolve. If the value is optional,
the bundle will resolve even if the required bundle does not exist.
• resolution – 如果值是mandatory (默認(rèn)值),那么required bundle必須存在用于解析這個(gè)bundle。如果值是optional,那么這個(gè)bundle將會(huì)被解析,即使required bundle不存在。
The following matching attribute is architected by the Framework:
以下匹配屬性由框架構(gòu)造:
• bundle-version – The value of this attribute is a version range to
select the bundle version of the required bundle. See Version Ranges on
page 28. The default value is [0.0.0,∞).
• bundle-version – 這個(gè)屬性的值是一個(gè)版本范圍,用于選擇required bundle的版本。默認(rèn)值是[0.0.0,∞)。
A given package may be available from more than one of the required
bundles. Such packages are named split packages because they derive
their contents from different bundles. If these different bundles
provide the same classes unpredictable shadowing of classes can arise,
see Issues With Requiring Bundles on page 66. However, split packages
without shadowing are explicitly permitted.
For example, take the following setup:
A: Require-Bundle: B
Export-Package: p
B: Export-Package: p;partial=true;mandatory:=partial
If bundle C imports package p, it will be wired to package A.p, however
the contents will come from B.p > A.p. The mandatory attribute on
bundle B’s export definition ensures that bundle B is not accidentally
selected as exporter for package p. Split packages have a number
drawbacks that are discussed in Issues With Requiring Bundles on page
66.
如果bundle C引入包p,它將被連接到包A.p,可是這個(gè)包是從B.p到A.p。bundle B的輸出定義的強(qiáng)制屬性確保了bundle B不會(huì)被意外的選擇為包p的輸出者。
Resources and classes from a split package must be searched in the
order in which the required bundles are specified in the Require-Bundle
header.
As an example, assume that a bundle consists of a number of bundles and
a number of language resources (also bundles) that are optional.
Require-Bundle: com.acme.facade;visibility:=reexport,
com.acme.bar.one;visibility:=reexport,
com.acme.bar.two;visibility:=reexport,
com.acme.bar._nl;visibility:=reexport;resolution:=optional,
com.acme.bar._en;visibility:=reexport;resolution:=optional
A bundle may both import packages (via Import-Package) and require one
or more bundles (via Require-Bundle), but if a package is imported via
Import-Package, it is not also visible via Require-Bundle:
Import-Package takes priority over Require-Bundle, and packages which
are exported by a required bundle and imported via Import-Package must
not be treated as split packages.
In order to be allowed to require a named bundle, the requiring bundle
must have BundlePermission[<bundle symbolic name>, REQUIRE],
where the bundle symbolic name is the name of the bundle that is
required. The required bundle must be able to provide the bundle and
must therefore have BundlePermission[<bundle symbolic name>,
PROVIDE], where the name designates the requiring bundle. In the case a
Fragment bundle requires another bundle, the Bundle Permission must be
checked against the Fragment bundle’s Protection Domain.
一個(gè)bundle可以同時(shí)引入包(通過Import-Package)和require一個(gè)或多個(gè)bundles(通過Require-Bundle),
但是如果一個(gè)包通過Import-Package被引入,那么通過Require-Bundle引入的相同的包不會(huì)可見,因?yàn)镮mport-
Package的優(yōu)先級(jí)大于Require-Bundle,被required
bundle輸出并通過Import-Package引入的包不能當(dāng)作split包來(lái)對(duì)待。
為了被允許需求一個(gè)命名bundle,requiring bundle必須有BundlePermission[<bundle
symbolic name>, REQUIRE](bundle權(quán)限),這里的bundle symbolic
name是被需要的bundle的名字。這個(gè)被需要的bundle必須能提供自己出去,因此它必須有
BundlePermission[<bundle symbolic name>, PROVIDE],這里的bundle
symbolic name指向那個(gè)requiring
bundle。在片段bundle需求其他bundle的情況下,bundle權(quán)限必須與片段bundle的域保護(hù)進(jìn)行核查(這里應(yīng)該是指宿主
bundle的權(quán)限)。
3.13.2 Split Package Compatibility
A package is a split package whenever there are multiple sources for
the package; only bundles using the Require-Bundle header can have
split packages.
A source is a bundle that provides the given package. Both the required
bundles as well as the requiring bundle can act as a source. The
required bundles and the requiring bundle can only contribute their
exported packages.
Exported split packages from two bundles are compatible if the package sources for one are a subset of the other.
對(duì)于一個(gè)包來(lái)說,只要有多個(gè)源,那它就是一個(gè)分隔包;只有使用頭Require-Bundle的bundle才有分隔包。
一個(gè)源是提供了這個(gè)包的bundle。required bundles和requiring bundle都可以成為一個(gè)源,它們只能分發(fā)它們自己的輸出包。
從兩個(gè)bundle輸出的分隔包是兼容的,如果這個(gè)包的其中一個(gè)源是另一個(gè)源的子集。
3.13.3 Issues With Requiring Bundles
The preferred way of wiring bundles is to use the Import-Package and
Export-Package headers because they couple the importer and exporter to
a much lesser extent. Bundles can be refactored to have a different
package composition without causing other bundles to fail.
The Require-Bundle header provides a way for a bundle to bind to all
the exports of another bundle, regardless of what those exports are.
Though this can seem convenient at first, it has a number of drawbacks:
連接bundles的首選方式是使用頭Import-Package和Export-Package,因?yàn)樗鼈儗⑤敵稣吆鸵胝哌B接到一個(gè)很小的范圍,bundles可以被重構(gòu)來(lái)含有一個(gè)不同的組成包,而不需要使其他bundles失敗。
頭Require-Bundle提供的方式是綁定那個(gè)bundle所有的輸出包,而不管這些輸出包是什么。盡管這看起來(lái)很方便,但是有以下缺點(diǎn):
• Split Packages – Classes from the same package can come from
different bundles with Require bundle, such a package is called a split
package. Split packages have the following drawbacks:
• Split Packages – 同一個(gè)包中的類,可以來(lái)自不同的bundles,這個(gè)包成為分隔包。分隔包有以下缺點(diǎn):
• Completeness – Split packages are open ended, there is no way to
guarantee that all the intended pieces of a split package have actually
been included.
• Completeness – 分隔包是入口處,沒有辦法保證所有這個(gè)分隔包所需的部分都已經(jīng)被包含了。
• Ordering – If the same classes are present in more than one
required bundle, then the ordering of Require-Bundle is significant. A
wrong ordering can cause hard to trace errors, similar to the
traditional class path model of Java.
• Ordering – 如果相同的類出現(xiàn)在多個(gè)required bundle中,那么Require-Bundle的順序就變得很重要了,一個(gè)錯(cuò)誤的順序會(huì)讓錯(cuò)誤跟蹤變得很難,這與JAVA傳統(tǒng)的類路徑模式相似。
• Performance – A class must be searched in all providers when
packages are split. This increases the number of times that a
ClassNotFoundException must be thrown which can introduce a significant
overhead.
• Performance –在分隔包中,一個(gè)類必須被查找于所有的提供者,這會(huì)增加ClassNotFoundException必須被拋出的次數(shù),這是很大的性能支出。
• Confusing – It is easy to find a setup where there is lots of
potential for confusion. For example, the following setup is
non-intuitive.
A: Export-Package: p;uses:=q Import-Package: q
B: Export-Package: q
C: Export-Package: q
D: Require-Bundle: B, C Import-Package: p
In this example, bundle D merges the split package q from bundles B and
bundle C, however, importing package p from bundle A puts a uses
constraint on package p for package q. This implies that bundle D can
see the valid package q from bundle B but also the invalid package q
from bundle C. This wiring is allowed because in almost all cases there
will be no problem. However, the consistency can be violated in the
rare case when package C.q contains classes that are also in package
B.q.
在這個(gè)例子中,bundle D合并了bundle B和C的包q,可是A.p,為包q設(shè)置了uses指令,約束到包A.p上。這暗示了bundle D可以看見可用的B.q,也可以看見不可用的C.q(頭
Require-Bundle中,B在C前面)。這個(gè)連接是被允許的,在大多數(shù)案例中不會(huì)有問題。但是,當(dāng)C.q和B.q中包含同相同的類時(shí),就會(huì)發(fā)生問題。
• Mutable Exports – The feature of visibility:=reexport that the export
signature of the requiring bundle can unexpectedly change depending on
the export signature of the required bundle.
• Mutable Exports – visibility:=reexport的特性,requiring bundle的輸出信號(hào)可以根據(jù)required bundle的輸出信號(hào)而發(fā)生不可預(yù)期的改變。
• Shadowing – The classes in the requiring bundle that are shadowed by
those in a required bundle depend on the export signature of the
required bundle and the classes the required bundle contains. (By
contrast, Import-Package, except with resolution:=optional, shadows
whole packages regardless of the exporter.)
• Shadowing – the requiring bundle中的類會(huì)被那些required bundle遮擋,根據(jù)required
bundle的輸出信號(hào)和包含的類(相比之下,Import-Package,除了resolution:=optional,會(huì)遮擋所有的包而不管輸出
者)。(深層優(yōu)先的類路徑查找順序)
• Unexpected Signature Changes – The Require-Bundle directive
visibility:=private (the default) may be unexpectedly overridden in
some circumstances as the following example shows.
• Unexpected Signature Changes – 在某些情況下,Require-Bundle的指令visibility:=private可能會(huì)出乎預(yù)料的被重載
A: p (private, not exposed in manifest)
Require-Bundle: B;visibility:=reexport,
C;visibility:=private
B: Export-Package: p
C: Export-Package: p
The export signature of bundle A will consist of only package p.
However, package p is split. The Framework searches for a class in
package p in bundle B, then bundle C, and last bundle A.
So the visibility:=private directive on Require-Bundle C had no effect
relative to package p. However, if bundle B was changed to stop
exporting package p, then the directive would take effect and package p
would drop out of bundle A's export signature. This is depicted in
Figure 3.22.
bundle A的輸出信號(hào)僅由包p組成,可是包p是個(gè)分隔包??蚣軙?huì)先在bundle B中的包p中查找一個(gè)類,然后再在bundle
C中查找,最后才查找bundle A。所以Require-Bundle
C上的指令visibility:=private不會(huì)影響到包p。但是,如果bundle
B停止輸出包p,那么這個(gè)指令將會(huì)受到影響,包p也將退出bundle A的輸出信號(hào)。
3.14 Fragment Bundles
Fragments are bundles that are attached to a host bundle by the
Framework. Attaching is done as part of resolving: the Framework
appends the relevant definitions of the fragment bundles to the host’s
definitions before the host is resolved. Fragments are therefore
treated as part of the host, including any permitted headers; they must
not have their own class loader. Fragments must have their own
Protection Domain.
A key use case for fragments is providing translation files for
different locales. This allows the translation files to be treated and
shipped independently from the main application bundle.
When an attached fragment bundle is updated, the content of the
previous fragment must remain attached to its host bundle. The new
content of the updated fragment must not be allowed to attach to the
host bundle until the Framework is restarted or the host bundle is
refreshed. During this time, an attached fragment will have two
versions: the old version, attached to the
old version of the host, and a new fragment bundle that can get attached to a new version or to a different host bundle.
片段是由框架附加在一個(gè)主bundle上的bundles。附加過程是解析過程的一部分:框架在主bundle被解析之前將片段bundles的相關(guān)定義
附加到主bundle的定義上。因此,片段可看作主bundle的一部分,包括所有允許的頭。片段必須不能有它們自己的class
loader。片段必須有它們自己的保護(hù)域。
片段的一個(gè)重要案例是為不同的locales提供翻譯文件。這允許翻譯文件可獨(dú)立于主應(yīng)用bundle被處理和裝載。
當(dāng)一個(gè)片段被更新時(shí),上一個(gè)片段的內(nèi)容必須被保留在它的宿主bundle上。更新片段的內(nèi)容必須不能被附加到那個(gè)宿主bundle,知道框架重啟或那個(gè)宿
主bundle被刷新。期間,這個(gè)片段會(huì)有2個(gè)版本:老版本,附加在老版本的宿主bundle,新的片段能附加在一個(gè)新版本的bundle或是其他宿主
bundle上。
In this case, the Package Admin service must return information only
for the last version of the supplied bundles. In the previous described
case, the getHosts method must return the host bundle of the new
version of the fragment bundle, and the getFragments method must return
the fragment bundles attached to the new version of the host bundle.
在這里,Package Admin
service必須只能為那個(gè)提供的bundle最后面的那個(gè)版本返回信息。在前面的例子中,getHosts方法必須返回新版本片段bundle的宿主
bundle,getFragments方法必須返回附加在新的主bundle上的片段bundle。
When attaching a fragment bundle to a host bundle the Framework must perform the following steps:
當(dāng)附加一個(gè)片段bundle到一個(gè)主bundle時(shí),框架必須執(zhí)行以下步驟:
1 Append the import definitions for the Fragment bundle that do not
conflict with an import definition of the host to the import
definitions of the host bundle. A Fragment can provide an import
statement for a private package of the host. The private package in the
host is hidden in that case.
2 Append the Require-Bundle entries of the fragment bundle that do not
conflict with a Require-Bundle entry of the host to the Require-Bundle
entries of the host bundle.
3 Append the export definitions of a Fragment bundle to the export
definitions of the host bundle unless the exact definition (directives
and attributes must match) is already present in the host. Fragment
bundles can therefore add additional exports for the same package name.
The bundle-version attributes and bundle-symbolic-name attributes will
reflect the host bundle.
1. 將片段bundle中不影響主bundle引入定義的引入定義添加到主bundle的引入定義中。一個(gè)片段可以為主bundle中一個(gè)私有包提供引入聲明,主bundle中的那個(gè)私有包是隱藏的。
2. 將片段bundle中不影響主bundle的Require-Bundle實(shí)體的Require-Bundle實(shí)體添加到zhu主bundle的Require-Bundle實(shí)體中。
3.
將片段bundle中不影響主bundle輸出定義的輸出定義添加到主bundle的輸出定義中,除非主bundle中已經(jīng)有了這樣一個(gè)定義(指令和屬性
必須匹配)。因此,片段bundles可以有對(duì)同一個(gè)包名的輸出。屬性bundle-version和屬性bundle-symbolic-name將會(huì)
反射到主bundle。
A host and a fragment conflict when they cannot resolve to provide a
consistent class space. If a conflict is found, the Fragment bundle is
not attached to the host bundle.
A Fragment bundle must enter the resolved state only if it has been
successfully attached to its host bundle. During runtime, the
fragment’s JAR is searched after the host’s bundle class path as
described in Fragments During Runtime on page 70.
A Fragment bundle can not be required by another bundle with the Require-Bundle header.
當(dāng)一個(gè)主bundle和一個(gè)片段bundle不能解析來(lái)提供一個(gè)一致的的類空間時(shí),它們會(huì)發(fā)生沖突,片段bundle將不再添加到這個(gè)主bundle。
一個(gè)片段bundle僅當(dāng)它成功附加到一個(gè)主bundle后,它才進(jìn)入resolved狀態(tài),它的JAR包將在主bundle的類路徑之后被查找。
其他bundle不能使用頭Require-Bundle來(lái)require一個(gè)片段bundle。
3.14.1 Fragment-Host
A fragment is a bundle that is attached to one other bundle called its
host bundle. The components of the fragment, like the Bundle-Classpath
and other definitions, are added at the end of the related definitions
of the host bundle. In the case of the Export-Package header, bundle
dependent attributes like bundle-version and bundle-symbolic-name come
from the host. All classes and resources within the fragment bundle
must be loaded using the class loader of the host bundle.
一個(gè)片段是一個(gè)bundle,被它附加的另一個(gè)bundle叫做它的宿主bundle。片段bundle的組件,就像Bundle-Classpath或
其他定義,被添加在主bundle的相關(guān)定義的末尾。在頭Export-Package中,bundle依賴的屬性,例如bundle-version和
bundle-symbolic-name均來(lái)自主bundle。片段bundle中所有的類和資源必須使用主bundle的class
loader加載。
The Fragment-Host manifest header must conform to the following syntax:
Fragment-Host ::= bundle-description
bundle-description ::= symbolic-name
(';' parameter ) * // See 1.3.2
The following directives are architected by the Framework for Fragment-Host:
框架為Fragment-Host構(gòu)造了以下指令:
• extension – Indicates this extension is a system or boot class path
extension. It is only applicable when the Fragment-Host is the System
Bundle. This is discussed in Extension Bundles on page 72. The
following values are supported:
• extension – 指這個(gè)擴(kuò)展是系統(tǒng)或boot 類路徑擴(kuò)展,它只能在Fragment-Host(宿主bundle)是系統(tǒng)bundle的情況下才可用。支持以下值:
• framework - The fragment bundle is a Framework extension bundle.
• framework - 片段bundle是框架的擴(kuò)展bundle。
• bootclasspath - The fragment bundle is a boot class path extension bundle.
• bootclasspath - 片段bundle是boot類路徑擴(kuò)展bundle。
The fragment must be the bundle symbolic name of the implementation
specific system bundle or the alias system.bundle. The Framework should
fail to install an extension bundle when the bundle symbolic name is
not referring to the system bundle.
片段必須是實(shí)現(xiàn)特殊系統(tǒng)bundle的bundle標(biāo)記名或別名system.bundle(應(yīng)該是指片段bundle的標(biāo)記名)。當(dāng)片段的標(biāo)記名沒有引用到系統(tǒng)bundle時(shí),框架必須使這個(gè)擴(kuò)展安裝失敗。
The following attributes are architected by the Framework for Fragment-Host:
• bundle-version – The version range to select the bundle that provides
the host bundle. See Version Matching on page 41. The default value is
[0.0.0,∞).
• bundle-version – 版本范圍,用于選擇提供宿主的bundle
When a fragment bundle becomes resolved, the Framework must attach the
fragment bundle to the selected host bundle with the highest version.
When a fragment bundle is attached to its host bundle, it logically
becomes part of it. All classes and resources within the fragment
bundle must be loaded using the class loader of its host bundle. The
fragment bundles of a host bundle must be attached to the host bundle
in the order that the fragment bundles are installed, which is in
ascending bundle ID order. If an error occurs during the attachment of
a fragment bundle then the fragment bundle must not be attached to the
host. A fragment bundle must enter the resolved state only if it has
been successfully attached to its host bundles.
In order for a host bundle to allow fragments to attach, the host
bundle must have BundlePermission[<bundle symbolic name>,HOST].
In order to be allowed to attach to a host bundle, a fragment bundle
must have BundlePermission[<bundle symbolic name>,FRAGMENT].
當(dāng)一個(gè)片段bundle解析之后,框架必須將這個(gè)片段bundle附加到被選擇的版本最高的主bundle上。
當(dāng)一個(gè)片段bundle被附加到它的主bundle后,理論上它就成了主bundle的一部分。片段bundle中所有的類和資源必須使用它的宿主
bundle的class
loader去加載。一個(gè)主bundle的片段bundles必須按照它們被安裝的順序附加到主bundle上,也就是根據(jù)他們的bundle
ID的升序。如果在附加過程中發(fā)生錯(cuò)誤,那么片段bundle不能附加到主bundle上。一個(gè)片段bundle只有在成功附加到它的所有主
bundles后才能進(jìn)入resolved狀態(tài)。
為了使一個(gè)主bundle允許被附加片段,這個(gè)主bundle必須有BundlePermission[<bundle symbolic
name>,HOST],為了使一個(gè)片段被允許附加到一個(gè)主bundle,這個(gè)片段bundle必須有a fragment bundle
must have BundlePermission[<bundle symbolic name>,FRAGMENT]
3.14.2 Fragments During Runtime
All class or resource loading of a fragment is handled through the
host’s class loader, a fragment must never have its own class loader.
Fragment bundles are treated as if they are an intrinsic part of their
host.
Though a fragment bundle does not have its own class loader, it still
must have a separate Protection Domain when it is not an extension
fragment. Each fragment can have its own permissions linked to the
fragment bundle’s location and signer.
A host bundle’s class path is searched before a fragment’s class path.
This implies that packages can be split over the host and any of its
fragments. Searching the fragments must be done in ascending bundle ID
order. This is the order that the fragment bundles were installed.
片段所有類和資源的加載都由它的主bundle的class loader來(lái)處理,它不能擁有自己的class loader。片段bundles被看成是它們的宿主bundle的一部分。
盡管一個(gè)片段bundle沒有它自己的class loader,如果它不是一個(gè)擴(kuò)展片段,它還是必須有一個(gè)保護(hù)域。每個(gè)片段都有它自己的連接到片段bundle的路徑和簽名者的權(quán)限。
一個(gè)主bundle的類路徑在片段bundle的類路徑之前被查找,這暗示了包可以被分割到主bundle和片段bundles。片段的查找必須根據(jù)它們被安裝后的ID的升序進(jìn)行。
Figure 3.23 shows a setup with two fragments. Bundle B is installed
before bundle C and both bundle B and bundle C attach to bundle A. The
following table shows where different packages originate in this setup.
Note that the order of the append (>) is significant.
圖3.23顯示了兩個(gè)片段的設(shè)置。bundle B在C之前被安裝,它們都被附加到bundle A。下面的表格顯示了這個(gè)安裝的兩個(gè)包的本質(zhì)區(qū)別,注意>的順序是很重要的。
Table 3.4 Effect of fragments on searching
Package Requested |
From |
Remark |
p |
A.p > B.p |
Bundle
A exports package p, therefore, it will search its class path for p.
This class path consists of the JAR and then its Fragment bundles. |
q |
D.q |
The import does not handle split packages and package q is imported from bundle D. Therefore, C.q is not found. |
r |
A.r > B.r |
Package r is not imported and therefore comes from the class path. |
s |
C.s |
|
t |
B.t > C.t |
|
In the example above, if package p had been imported from bundle D, the
table would have looked quite different. Package p would have come from
bundle D, and bundle A’s own contents as well as the contents of bundle
B would have been ignored.
在上面的例子中,如果包p是從bundle D引入的,那么這個(gè)表格將發(fā)生很大變化。包p來(lái)自bundle D,A.p和B.p將被忽略(D的類路徑先被查找)。
If package q had bundle D, then the class path would have to be searched, and A.q would have consisted of A.q > C.q.
Fragments must remain attached as long as the host remains resolved.
When a host bundle becomes unresolved, then all attached Fragment
bundles must be detached from the host bundle. When a fragment bundle
becomes unresolved the Framework must:
• Detach it from the host
• Re-resolve the host bundle
• Reattach the remaining attached fragment bundles.
A Fragment bundle can become unresolved by calling the refreshPackages
method or the resolveBundle method on itself or on its host.
主bundle處于resolved期間,片段bundle必須一直保持附加狀態(tài)。當(dāng)一個(gè)主bundle變成unresolved時(shí),所有的附加片段bundle必須從主bundle分離出來(lái)。當(dāng)一個(gè)片段bundle變得unresolved時(shí),框架必須:
• 將其分離出主bundle
• 重新解析主bundle
• 重新附加片段bundles
一個(gè)片段bundle可以通過調(diào)用方法refreshPackages或調(diào)用主bundle的或它自己的resolveBundle方法變成unresolved。
3.14.3 Illegal Manifest Header for Fragment Bundles
The following list contains the headers that must not be used in a fragment bundle:
一下列表包含了在一個(gè)片段bundle中必須不能使用的頭:
• Bundle-Activator
3.15 Extension Bundles
Extension bundles can deliver optional parts of the Framework
implementation or provide functionality that must reside on the boot
class path. These packages cannot be provided by the normal
import/export mechanisms.
擴(kuò)展bundles能夠提供框架實(shí)現(xiàn)的可選部分或提供必須在boot類路徑中的功能(包)。這些包不能使用平常的引入/輸出機(jī)制。
Boot class path extensions are necessary because certain package
implementations assume that they are on the boot class path or are
required to be available to all clients. An example of a boot class
path extension is an implementation of java.sql such as JSR 169. Boot
class path extensions are not required to be implemented by a compliant
framework, see Optional on page 64.
Boot類路徑擴(kuò)展是有必要的,因?yàn)槟承?shí)現(xiàn)包假設(shè)它們處于boot類路徑上或?qū)λ衦equired的客戶端可用。boot類路徑擴(kuò)展的一個(gè)例子是java.sql的實(shí)現(xiàn),就像JSR 169.boot類路徑擴(kuò)展的實(shí)現(xiàn)不是必須的。
Framework extensions are necessary to provide implementation aspects of
the Framework. For example, a Framework vendor could supply the
optional services like Permission Admin service and Start Level service
with Framework extension bundles.
框架擴(kuò)展對(duì)于提供框架的實(shí)現(xiàn)部分是由必要的。例如,一個(gè)框架提供者可以通過擴(kuò)展bundles提供一些可選服務(wù),就像Permission Admin service和 Start Level service
An extension bundle should use the bundle symbolic name of the
implementation system bundle, or it can use the alias of the system
bundle, which is system.bundle.
一個(gè)擴(kuò)展bundle應(yīng)該使用系統(tǒng)實(shí)現(xiàn)bundle的標(biāo)記名,或使用系統(tǒng)bundle的別名system.bundle。
The following example uses the Fragment-Host manifest header to specify
an extension bundle for a specific Framework implementation.
下面這個(gè)例子使用頭Fragment-Host來(lái)指定一個(gè)框架細(xì)節(jié)實(shí)現(xiàn)的擴(kuò)展bundle。
Fragment-Host: com.acme.impl.framework; extension:=framework
The following example uses the Fragment-Host manifest header to specify a boot class path extension bundle.
Fragment-Host: system.bundle; extension:=bootclasspath
The following steps describe the life cycle of an extension bundle:
下面的步驟描述了一個(gè)擴(kuò)展bundle的生命周期:
1 When an extension bundle is installed it enters the INSTALLED state.
2 The extension bundle is allowed to enter the RESOLVED state at the
Frameworks discretion, which can require a Framework re-launch.
3 If the extension bundle is refreshed then the Framework must
shutdown, the host VM must terminate, and the Framework must be
relaunched.
4 If a RESOLVED extension bundle is refreshed then the Framework must
shutdown; the host VM must terminate and framework must be relaunched.
5 When a RESOLVED extension bundle is updated or UNINSTALLED, it is not
allowed to re-enter the RESOLVED state. If the extension bundle is
refreshed then the Framework must shutdown; the host VM must terminate
and framework must be re-launched.
1. 當(dāng)一個(gè)擴(kuò)展bundle被安裝后,它進(jìn)入INSTALLED狀態(tài)。
2. 擴(kuò)展bundle可以進(jìn)入RESOLVED狀態(tài),這由框架自行決定,但是需要框架重啟。
3. 如果這個(gè)擴(kuò)展bundle被刷新,那么框架必須shutdown,VM必須終止,框架必須被重啟。
4. 如果一個(gè)resolved狀態(tài)的擴(kuò)展bundle被刷新,那么框架必須shutdown,VM必須終止,框架必須被重啟。
5. 當(dāng)一個(gè)resolved狀態(tài)的擴(kuò)展bundle被更新或進(jìn)入uninstalled狀態(tài)時(shí),它將不允許重新進(jìn)入resolved狀態(tài),如果它被刷新,那么框架必須shutdown,VM必須終止,框架必須被重啟。
It is valid to update an extension bundle to a bundle of another type.
If the old extension bundle is resolved then it must be attached as a
fragment to the system bundle. When this bundle is updated the old
content of the bundle must remain attached to the system bundle until
the system bundle is refreshed or the extension bundle is refreshed
(using Package Admin service). This must initiate a VM and Framework
restart. When the framework comes back up the new content of the bundle
may be resolved.
All Bundle events should be dispatched for extension bundles as for ordinary bundles.
可以將擴(kuò)展bundle更新成其他類型的bundle。如果原來(lái)的那個(gè)擴(kuò)展bundle處于resolved狀態(tài),那么它必須被作為一個(gè)片段附加到系統(tǒng)
bundle。當(dāng)這個(gè)bundle被更新后,它以前的內(nèi)容必須保持附加在系統(tǒng)bundle知道系統(tǒng)bundle被刷新或這個(gè)擴(kuò)展bundle被刷新。這必
須使一個(gè)VM和框架重啟。當(dāng)框架重啟后,新bundle可以被解析。
所有的bundle事件必須被分發(fā)到擴(kuò)展bundle,與普通bundle一樣。
3.15.1 Illegal Manifest Headers for Extension Bundles
An extension bundle must throw a BundleException if it is installed or updated and it specifies any of the following headers.
如果一個(gè)擴(kuò)展bundle被安裝或更新并且指定了下列任何一個(gè)頭,必須拋出一個(gè)BundleException
• Import-Package
• Require-Bundle
• Bundle-NativeCode
• DynamicImport-Package
• Bundle-Activator
Both boot class path and framework extension bundles are permitted to
specify an Export-Package header. Any exported packages specified by a
framework extension bundle must be exported by the System Bundle when
the extension bundle is resolved.
boot類路徑和框架擴(kuò)展bundle都可以指定頭Export-Package。當(dāng)擴(kuò)展bundle被解析時(shí),所有它指定的輸出包都必須由系統(tǒng)bundle來(lái)輸出。
3.15.2 Class Path Treatment
A boot class path extension bundle’s JAR file must be appended to the
boot class path of the host VM. A framework extension bundle’s JAR is
appended to the class path of the Framework.
Extension bundles must be appended to their class path in the order in
which the extension bundles are installed: that is, ascending bundle ID
order.
How a framework configures itself or the boot class path to append the
extension bundle’s JAR is implementation specific. In some execution
environments, it may be impossible to support extension bundles. In
such environments, the Framework must throw a BundleException when such
an
extension bundle is installed. The resulting Bundle Exception must have a cause of type UnsupportedOperationException.
一個(gè)boot類路徑擴(kuò)展bundle的JAR包文件必須添加到VM的boot類路徑中,一個(gè)框架擴(kuò)展bundle的JAR包文件必須被添加到框架的類路徑中。
擴(kuò)展bundle必須根據(jù)他們被安裝時(shí)ID的升序被添加到它們的類路徑中。
一個(gè)框架配置或boot類路徑如何添加擴(kuò)展bundle的JAR包文件是一個(gè)特殊實(shí)現(xiàn)。在一個(gè)執(zhí)行環(huán)境中,可能不支持?jǐn)U展bundle。如果是這樣,擴(kuò)展
bundle被安裝時(shí),框架必須拋出一個(gè)BundleException ,包含 cause of
UnsupportedOperationException
3.16 Security
3.16.1 Extension Bundles
In an environment that has Java 2 security enabled the Framework must
perform an additional security check before allowing an extension
bundle to be installed. In order for an extension bundle to
successfully install, the Framework must check that the extension
bundle has All Permissions assigned to it. This means that the
permissions of an extension bundle must be setup before the extension
bundle is installed.
在JAVA2安全環(huán)境中,框架必須在允許擴(kuò)展bundle被安裝之前執(zhí)行一個(gè)額外的安全檢查。為了成功安裝一個(gè)擴(kuò)展bundle,框架必須檢查擴(kuò)展bundle的權(quán)限。也就是說在擴(kuò)展bundle被安裝之前,它的權(quán)限必須被設(shè)置。
AllPermission must be granted to extension bundles because they will be
loaded under the Protection Domain of either the boot class path or the
Framework implementation. Both of these Protection Domains have All
Permissions granted to them. It must therefore not be allowed for an
extension bundle to be installed unless it already has been granted
AllPermissions.
擴(kuò)展bundle必須被授予所有權(quán)限,因?yàn)樗麄儗⒈患虞d于它們的boot類路徑或框架實(shí)現(xiàn)的保護(hù)域中。這些保護(hù)域都被授予了所有權(quán)限。因此除非一個(gè)擴(kuò)展bundle有所有權(quán)限,否則不能被安裝。
The installer of an extension bundle must have
AdminPermission[<extension bundle>,EXTENSIONLIFECYCLE] to install
an extension bundle.
擴(kuò)展bundle的安裝者必須有AdminPermission[<extension bundle>,EXTENSIONLIFECYCLE]權(quán)限。
3.16.2 Bundle Permission
Most package sharing permissions are based on Package Permission.
However, fragments and required bundles use the bundle symbolic name to
handle sharing. The Bundle Permission is used to control this type of
package sharing.
大部分包共享權(quán)限是基于Package Permission的??墒瞧蝏undle和required bundles是使用bundle標(biāo)記名來(lái)操作共享的。Bundle Permission就是用來(lái)控制這種類型的包共享。
The name parameter of the Bundle Permission is a bundle symbolic name.
The symbolic name is used as the identifier for the target bundle. A
wild card (’.*’ \u002E,\u002A) is permitted at the end of the name.
Bundle Permission的參數(shù)name是一個(gè)bundle的標(biāo)記名,這個(gè)標(biāo)記名用作目標(biāo)bundle的標(biāo)識(shí)符,通配符"*"可以跟在名字的結(jié)尾。
For example, if fragment bundle A attaches to its host bundle B then
fragment bundle A requires BundlePermission("B", "fragment") so that A
is permitted to target host bundle B. The direction of the actions is
depicted in Figure 3.24.
The following actions are architected:
• provide – Permission to provide packages to the target bundle.
• require – Permission to require packages from the target bundle.
• host – Permission to attach to the target fragment bundle.
• fragment – Permission to attach as a fragment to the target host bundle.
When a fragment contains a Require-Bundle header, the Framework must check the permission against the domain of the fragment.
3.16.3 Package Permission
Bundles can only import and export packages for which they have the
required permission. A PackagePermission must be valid across all
versions of a package.
A PackagePermission has two parameters:
• The package that may be exported or imported. A wildcard may be used.
The granularity of the permission is the package, not the class name.
• The action, either IMPORT or EXPORT. If a bundle has permission to
export a package, the Framework must automatically grant it permission
to import the package.
A PackagePermission with * and EXPORT as parameters allows the import and export of any package.
When a fragment adds imports and exports to the host, the framework
must check the protection domain of the fragment and not of the related
host.
3.16.4 Resource Permissions
A Framework must always give a bundle the RESOURCE, METADATA, and CLASS
AdminPermission actions to access the resources contained within:
• Itself
• Any attached fragments
• Any resources from imported packages
A resource in a bundle may also be accessed by using certain methods on
Bundle. The caller of these methods must have AdminPermission[bundle,
RESOURCE].
If the caller does not have the necessary permission, a resource is not
accessible and null must be returned. Otherwise, a URL object to the
resource must be returned. These URLs are called bundle resource URLs.
Once the URL object is returned, no further permission checks are
performed when the contents of the resource are accessed. The URL
object must use a scheme
defined by the Framework implementation.
Bundle resource URLs are normally created by the Framework, however, in
certain cases bundles need to manipulate the URL to find related
resources. For example, a URL can be constructed to a resource that is
in the same directory as a given resource.
URLs that are not constructed by the Framework must follow slightly
different security rules due to the design of the java.net.URL class.
Not all constructors of the URL class interact with the URL Stream
Handler classes (the implementation specific part). Other constructors
call at least the parseURL method in the URL Stream Handler where the
security check can take place.
This design makes it impossible for the Framework check the permissions during construction of a bundle resource URL.
The following constructors use the parseURL method and are therefore checked when a bundle resource URL is constructed.
URL(String spec)
URL(URL context, String spec)
URL(URL context, String spec, URLStreamHandler handler)
When one of these constructors is called for a bundle resource URL, the
implementation of the Framework must check the caller for the necessary
permissions in the parseURL method. If the caller does not have the
necessary permissions then the parseURL method must throw a Security
Exception. This will cause a Malformed URL Exception to be thrown by
the URL constructor. If the caller has the necessary permissions, then
the URL object is setup to access the bundle resource without further
checks.
The following java.net.URL constructors do not call the parseURL method
in the URL Stream Handler, making it impossible for the Framework to
verify the permission during construction.
URL(String protocol, String host, int port, String file)
URL(String protocol, String host, int port, String file,
URLStreamHandler handler)
URL(String protocol, String host, String file)
Bundle resource URLs that are created with these constructors cannot
perform the permission check during creation and must therefore delay
the permission check. When the content of the URL is accessed, the
Framework must throw a Security Exception if the caller does not have
AdminPermission[bundle, RESOURCE] for the bundle referenced by the URL.
3.16.5 Permission Checks
Since multiple bundles can export permission classes with the same
class name, the Framework must make sure that permission checks are
performed using the correct class. For example, a bundle that calls the
check-Permission method provides an instance of the Permission class:
void foo(String name) {
checkPermission(new FooPermission(name,"foo"));
}
This class of this Permission instance comes from a particular source.
Permissions can only be tested against instances that come from the
same source.
Therefore, the Framework needs to look up permissions based on class
rather than class name. When it needs to instantiate a permission it
must use the class of the permission being checked to do the
instantiation. This is a complication for Framework implementers;
bundle programmers are not affected.
Consider the following example:
Bundle A
Import-Package: p
Export-Package: q
Bundle B
Import-Package: p
• Bundle A uses a p.FooService. Usage of this class checks q.FooPermission whenever one of its methods is invoked.
• Bundle B has a FooPermission in its Protection Domain in a (Conditional) Permission Info object.
• Bundle B invokes a method in the FooService that was given by bundle A.
• The FooService calls the checkPermission method with a new FooPermission instance.
• The Framework must use a FooPermission object that is from the same
class loader as the given FooPermission object before it can call the
implies method. In this case, the FooPermission class comes from
package A.q.
After the permission check, bundle B will have a FooPermission
instantiated using a class from a package it does not import. It is
therefore possible that the Framework has to instantiate multiple
variations of the FooPermission class to satisfy the needs of different
bundles.