OSGi Service Platform Core Specification Release 4 - Life Cycle Layer
4.1 Introduction
The Life Cycle Layer provides an API to control the security and life cycle operations of bundles. The layer is based on the module and security layer.生命周期層提供了一個(gè)用于控制bundle的安全和生命周期操作的API,這個(gè)層是基于模塊層和安全層的。
4.1.1 Essentials
• Complete – The Life Cycle layer must implement an API that fully covers the installation, starting, stopping, updating, uninstallation, and monitoring of bundles.• Reflective – The API must provide full insight into the actual state of the Framework.
• Secure – It must be possible to use the API in a secure environment using fine-grained permissions. However, security must be optional.
• Manageable – It must be possible to manage a Service Platform remotely.
• Complete – 生命周期層必須實(shí)現(xiàn)一個(gè)全面涵蓋bundle的安裝,啟動(dòng),停止,更新,卸載和監(jiān)控的API。
• Reflective –這個(gè)API必須提供對框架的實(shí)際狀態(tài)的完整監(jiān)察。
• Secure – 必須能夠在一個(gè)細(xì)粒度權(quán)限的安全環(huán)境中使用API,但是安全必須是可選的。
• Manageable – 必須可以遠(yuǎn)程管理一個(gè)服務(wù)平臺(tái)。
4.1.2 Entities
• Bundle – Represents an installed bundle in the Framework.• Bundle Context – A bundle's execution context within the Framework. The Framework passes this to a Bundle Activator when a bundle is started or stopped.
• Bundle Activator – An interface implemented by a class in a bundle that is used to start and stop that bundle.
• Bundle Event – An event that signals a life cycle operation on a bundle. This event is received via a (Synchronous) Bundle Listener.
• Framework Event – An event that signals an error or Framework state change. The event is received via a Framework Listener.
• Bundle Listener – A listener to Bundle Events.
• Synchronous Bundle Listener – A listener to synchronously delivered Bundle Events.
• Framework Listener – A listener to Framework events.
• Bundle Exception – An Exception thrown when Framework operations fail.
• System Bundle – A bundle that represents the Framework.

4.2 Bundles
A bundle represents a JAR file that is executed in an OSGi Framework. The class loading aspects of this concept were specified in the Module Layer. However, the Module Layer does not define how a bundle is installed, updated, and uninstalled. These life cycle operations are defined here.一個(gè)bundle是一個(gè)在OSGi框架中被執(zhí)行的JAR文件。類加載方面的概念定義在模塊層中,但是模塊層沒有定義一個(gè)bundle如何被安裝,更新,卸載,這些就定義在生命周期層中。
The installation of a bundle can only be performed by another bundle or through implementation specific means (for example as a command line parameter of the Framework implementation).
一個(gè)bundle的安裝只能被執(zhí)行于另一個(gè)bundle或通過實(shí)現(xiàn)來執(zhí)行。
A Bundle is started through its Bundle Activator. Its Bundle Activator is identified by the Bundle-Activator manifest header. The given class must implement the BundleActivator interface. This interface has a start and stop method that is used by the bundle programmer to register itself as listener and start any necessary threads. The stop method must clean up and stop any running threads.
一個(gè)bundle通過它的Bundle Activator來啟動(dòng)。它的Bundle Activator由頭Bundle-Activator指定。這個(gè)指定的類必須實(shí)現(xiàn)BundleActivator 接口。這個(gè)接口有一個(gè)start方法和stop方法,給bundle開發(fā)人員注冊它自己的監(jiān)聽器和啟動(dòng)一些必要的線程。stop方法必須清除和停止所有由 它啟動(dòng)的線程。
Upon the activation of a bundle, it receives a Bundle Context. The Bundle Context interface’s methods can roughly be divided in the following categories:
• Information – Access to information about the rest of the Framework.
• Life Cycle – The possibility to install other bundles.
• Service Registry – The service registry is discussed in Service Layer on page 107.
激活bundle的時(shí)候,它會(huì)收到一個(gè)Bundle Context。這個(gè)Bundle Context接口的方法可以粗略地分成以下類別:
• Information – 訪問關(guān)于余下的框架信息(可理解為框架中其他bundle的信息)。
• Life Cycle – 可以安裝其他的bundles。
• Service Registry –
4.3 The Bundle Object
For each bundle installed in the OSGi Service Platform, there is an associated Bundle object. The Bundle object for a bundle can be used to manage the bundle’s life cycle. This is usually done with a Management Agent, which is also a Bundle.對于安裝在OSGi服務(wù)平臺(tái)中的每一個(gè)bundle,都有一個(gè)關(guān)聯(lián)的Bundle對象。這個(gè)對象可以用來管理bundle的生命周期。這通常是由一個(gè)Management Agent來完成,它也是個(gè)bundle。
4.3.1 Bundle Identifiers
A bundle is identified by a number of names that vary in their scope:一個(gè)bundle通過以下幾點(diǎn)來識(shí)別:
• Bundle identifier – A long that is a Framework assigned unique identifier for the full lifetime of a bundle, even if it is updated or the Framework is restarted. Its purpose is to distinguish bundles in a Framework. Bundle identifiers are assigned in ascending order to bundles when they are installed. The method getBundleId() returns a bundle’s identifier.
• Bundle location – A name assigned by the management agent (Operator) to a bundle during the installation. This string is normally interpreted as a URL to the JAR file but this is not mandatory. Within a particular Framework, a location must be unique. A location string uniquely identifies a bundle and must not change when a bundle is updated. The getLocation() method retrieves the location of a bundle.
• Bundle Symbolic Name – A name assigned by the developer. The combination of Bundle Version and Bundle Symbolic Name is a globally unique identifier for a bundle. The getSymbolicName() method returns the assigned bundle name.
• Bundle identifier – 一個(gè)長整型,是框架為一個(gè)bundle的整個(gè)生命周期所指派的唯一標(biāo)識(shí)符,即使這個(gè)bundle被更新或框架重啟。目的就是在框架中區(qū)別出 bundles。當(dāng)bundle安裝的時(shí)候,bundle標(biāo)識(shí)符是根據(jù)升序來進(jìn)行指派的,方法getBundleId()返回bundle的標(biāo)識(shí)符。
• Bundle location – 在安裝bundle的時(shí)候,由management agent指派給一個(gè)bundle的名字。這個(gè)字符串可以被理解為一個(gè)JAR文件的URL,但是不是強(qiáng)制的。這個(gè)URL在框架中必須是唯一的。在 bundle被更新的時(shí)候,這個(gè)URL必須不能被改變,它是一個(gè)bundle的具有唯一性的標(biāo)識(shí)符。
• Bundle Symbolic Name – 由開發(fā)人員指派的名字。bundle版本和bundle標(biāo)記名結(jié)合是一個(gè)bundle的全局唯一標(biāo)識(shí)符。
4.3.2 Bundle State
A bundle can be in one of the following states:一個(gè)bundle可以是以下其中一個(gè)狀態(tài):
• INSTALLED – The bundle has been successfully installed.
• RESOLVED – All Java classes that the bundle needs are available. This state indicates that the bundle is either ready to be started or has stopped.
• STARTING – The bundle is being started, the BundleActivator.start method will be called, and this method has not yet returned. When the bundle has an activation policy, the bundle will remain in the STARTING state until the bundle is activated according to its activation policy. See Activation Policies on page 85 for more information.
• ACTIVE – The bundle has been successfully activated and is running; its Bundle Activator start method has been called and returned.
• STOPPING – The bundle is being stopped. The BundleActivator.stop method has been called but the stop method has not yet returned.
• UNINSTALLED – The bundle has been uninstalled. It cannot move into another state.
• INSTALLED – bundle已經(jīng)被成功安裝。
• RESOLVED – bundle所需要的所有類都可用。這個(gè)狀態(tài)表示,這個(gè)bundle已經(jīng)準(zhǔn)備好被啟動(dòng)或是被停止了。
• STARTING – bundle正在被啟動(dòng),方法BundleActivator.start將被調(diào)用,但是還沒有return。如果bundle含有activation policy,那么bundle將一直處于STARTING,直到根據(jù)它的activation policy來激活它。
• ACTIVE – bundle被成功激活并運(yùn)行;它的BundleActivator.start方法被調(diào)用并return了。
• STOPPING – bundle正在被停職。BundleActivator.stop方法已經(jīng)被調(diào)用,但是還沒有return。
• UNINSTALLED – 卸載,它不能進(jìn)入其他狀態(tài)。

When a bundle is installed, it is stored in the persistent storage of the Framework and remains there until it is explicitly uninstalled. Whether a bundle has been started or stopped must be recorded in the persistent storage of the Framework. A bundle that has been persistently recorded as started must be started whenever the Framework starts until the bundle is explicitly
stopped. The Start Level service influences the actual starting and stopping of bundles. See Start Level Service Specification on page 203.
當(dāng)一個(gè)bundle被安裝后,它將被一直保存在框架的持久存儲(chǔ)中,知道它被卸載。不管一個(gè)bundle是被啟動(dòng)還是停止,都必須記錄在框架的持久存儲(chǔ)中。 一個(gè)bundle被永久地保存為啟動(dòng),那么它必須在框架啟動(dòng)時(shí)就被啟動(dòng),除非它被明確停止。啟動(dòng)級(jí)別服務(wù)會(huì)影響bundle的實(shí)際啟動(dòng)和停止。
The Bundle interface defines a getState() method for returning a bundle’s state.
Bundle接口定義了一個(gè)getState()方法來獲取bundle的狀態(tài)。
If this specification uses the term active to describe a state, then this includes the STARTING and STOPPING states.
如果規(guī)范使用術(shù)語active(激活)來描述一個(gè)狀態(tài),那么它表示STARTING或STOPPING狀態(tài)。
Bundle states are expressed as a bit-mask though a bundle can only be in one state at any time. The following code sample can be used to determine if a bundle is in the STARTING, ACTIVE, or STOPPING state:
bundle狀態(tài)可以被表示成一個(gè)bit-mask,盡管任何時(shí)候一個(gè)bundle只能處于一種狀態(tài)。下面的代碼示例可以用于決定bundle是否處于STARTING,ACTIVE或STOPPING狀態(tài)
if ((b.getState() & (STARTING | ACTIVE | STOPPING) != 0)
doActive()
doActive()
4.3.3 Installing Bundles
The BundleContext interface, which is given to the Bundle Activator of a bundle, defines the following methods for installing a bundle:• installBundle(String) – Installs a bundle from the specified location string (which should be a URL).
• installBundle(String,InputStream) – Installs a bundle from the specified InputStream object.
接口BundleContext,傳遞給一個(gè)bundle的Bundle Activator,定義一下方法用于安裝一個(gè)bundle
• installBundle(String) – 從指定的路徑(URL)安裝一個(gè)bundle
• installBundle(String,InputStream) – 從指定的InputStream 對象安裝一個(gè)bundle
A bundle must be valid before it is installed, otherwise the install must fail. The validity of a bundle is discussed in Bundle Validity on page 64.
一個(gè)bundle在安裝之前必須是可用的,否則安裝必須失敗。
Every bundle is uniquely identified by its location string. If an installed bundle is using the specified location, the installBundle methods must return the Bundle object for that installed bundle and not install a new bundle.
每一個(gè)bundle都由它的路徑字符串唯一識(shí)別,如果一個(gè)已經(jīng)安裝的bundle使用的是指定的路徑,installBundle 方法必須返回這個(gè)已經(jīng)安裝了的bundle對象,而不是安裝一個(gè)新bundle。
The Framework must assign a unique bundle identifier that is higher than any previous bundle identifier.
框架必須指派一個(gè)唯一bundle標(biāo)識(shí)符(long型),這個(gè)標(biāo)識(shí)符應(yīng)該大于先前安裝的任何bundle的標(biāo)識(shí)符。
The installation of a bundle in the Framework must be:
• Persistent – The bundle must remain installed across Framework and Java VM invocations until it is explicitly uninstalled.
• Atomic – The install method must completely install the bundle or, if the installation fails, the OSGi Service Platform must be left in the same state as it was in before the method was called.
框架中一個(gè)bundle的安裝必須是:
• Persistent – 這個(gè)bundle必須保持安裝于框架和JAVA VM調(diào)用器知道它被明確卸載。
• Atomic – 必須完全安裝一個(gè)bundle,如果安裝失敗,OSGi服務(wù)平臺(tái)必須返回到安裝前的狀態(tài)。
Once a bundle has been installed, a Bundle object is created and all remaining life cycle operations must be performed upon this object. The returned Bundle object can be used to start, stop, update, and uninstall the bundle.
一旦一個(gè)bundle被安裝,Bundle對象就被生成了,所有生命周期的操作必須執(zhí)行在這個(gè)對象之上。返回的Bundle對象可以start,stop,update和uninstall這個(gè)bundle。
4.3.4 Resolving Bundles
A bundle can enter the RESOLVED state when the Framework has successfully resolved the bundle's dependencies as described in the manifest. These dependencies are described in Resolving Process on page 48.當(dāng)框架成功解析一個(gè)bundle的manifest中表述的依賴關(guān)系后,這個(gè)bundle可以進(jìn)入RESOLVED狀態(tài)。
4.3.5 Starting Bundles
A bundle can be started by calling one of the start methods on its Bundle object or the Framework can automatically start the bundle if the bundle is ready and the autostart setting of the bundle indicates that it must be started.一個(gè)bundle可以通過調(diào)用start方法來啟動(dòng),或是框架能自動(dòng)啟動(dòng)這個(gè)bundle,如果它已經(jīng)準(zhǔn)備好,bundle的自動(dòng)啟動(dòng)設(shè)置表示它必須被啟動(dòng)。
A bundle is ready if following conditions are all met:
• The bundle can be resolved
• If the optional Start Level service is used, then the bundle’s start level is met.
如果滿足以下條件,一個(gè)bundle就準(zhǔn)備好可以啟動(dòng)了:
• bundle可以被解析
• 如果可選啟動(dòng)級(jí)別服務(wù)被啟用,那么bundle必須滿足這個(gè)啟動(dòng)級(jí)別
Once a bundle is started, a bundle must be activated, see Activation on page 84, to give control to the bundle so that it can initialize. This activation can take place immediately (eager activation), or upon the first class load from the bundle (lazy activation). A started bundle may need to be automatically started again by the framework after a restart or changes in the start level.
一旦一個(gè)bundle被啟動(dòng),它必須被激活,通過將控制權(quán)給它,以便它能初始化。這個(gè)激活可以立刻發(fā)生,或加載第一個(gè)來自這個(gè)bundle的的類時(shí) (lazy activation,懶激活)。重啟或修改啟動(dòng)級(jí)別之后,一個(gè)啟動(dòng)了的bundle可能需要由框架再次自動(dòng)將其啟動(dòng)。
The framework therefore maintains a persistent autostart setting for each bundle. This autostart setting can have the following values:
• Stopped – The bundle should not be started.
• Started with eager activation – The bundle must be started once it is ready and it must then be eagerly activated.
• Started with declared activation – The bundle must be started once it is ready and it must then be activated according to its declared activation policy. See Activation Policies on page 85.
因此框架必須為每一個(gè)bundle維護(hù)一個(gè)持久的自動(dòng)啟動(dòng)設(shè)置,這個(gè)啟動(dòng)設(shè)置可以有以下值:
• Stopped –bundle不應(yīng)該被啟動(dòng)。
• Started with eager activation – 一旦bundle準(zhǔn)備好,它必須被啟動(dòng),優(yōu)先激活
• Started with declared activation –一旦bundle準(zhǔn)備好,它必須被啟動(dòng),必須根據(jù)它的activation policy來激活它。
The Bundle interface defines the start(int) method for starting a bundle and controlling the autostart setting. The start(int) method takes an integer option, the following values have been defined for this option:
• 0 – Start the bundle with eager activation and set the autostart setting to Started with eager activation. If the bundle was already started with the lazy activation policy and is awaiting activation, then it must be activated immediately.
• START_TRANSIENT – Identical to 0 in behavior, however, the autostart setting must not be altered.If the bundle can not be started, for example, the bundle is not ready, then a Bundle Exception must be thrown.
• START_ACTIVATION_POLICY – Start the bundle using the activation policy declared in the manifest’s Bundle-ActivationPolicy header and set the autostart setting to Started with declared activation.
• START_ACTIVATION_POLICY | START_TRANSIENT – Start the bundle with the bundle’s declared activation policy but do not alter the autostart setting.
Bundle接口定義了方法start(int)來啟動(dòng)一個(gè)bundle并控制自動(dòng)啟動(dòng)設(shè)置。這個(gè)方法有一個(gè)整型參數(shù),為其定義了以下值:
• 0 – 優(yōu)先激活的啟動(dòng)bundle,將自動(dòng)啟動(dòng)設(shè)置 設(shè)置為Started with declared activation。如果這個(gè)bundle已經(jīng)被設(shè)置為lazy activation policy啟動(dòng),正在等待激活,那么它必須被馬上激活。
• START_TRANSIENT – 與0一樣,但是自動(dòng)啟動(dòng)設(shè)置必須不能被修改,如果bundle不能被啟動(dòng),例如,bundle沒有準(zhǔn)備好,那么一個(gè)BundleException必須被拋出。
• START_ACTIVATION_POLICY – 使用聲明在manifest中頭Bundle-ActivationPolicy里的激活策略來啟動(dòng)bundle,并將自動(dòng)啟動(dòng)設(shè)置 設(shè)置為Started with declared activation
• START_ACTIVATION_POLICY | START_TRANSIENT – 使用聲明的激活策略啟動(dòng)bundle,但不改變自動(dòng)啟動(dòng)設(shè)置。
The Framework must attempt to resolve the bundle, if not already resolved, when trying to start the bundle. If the bundle fails to resolve, the start method must throw a BundleException. In this case, the bundle’s autostart setting must still be set unless START_TRANSIENT is used.
當(dāng)啟動(dòng)bundle的時(shí)候,框架必須嘗試解析這個(gè)bundle,如果它還沒有被解析。如果解析失敗,start方法必須拋出一個(gè)BundleException。在這個(gè)情況下,bundle的自動(dòng)啟動(dòng)設(shè)置必須始終被設(shè)置,除非使用的是START_TRANSIENT。
When the start method returns without an exception, the state of the bundle will either be ACTIVE or STARTING, depending on the declared activation policy and whether it was used.
當(dāng)start方法return的時(shí)候,沒有exception,那么這個(gè)bundle的狀態(tài)將會(huì)是ACTIVE或STARTING,這依賴于declared activation policy和它是否被使用。
The start()method calls start(0).
The optional Start Level service influences the actual order of starting and stopping of bundles. See Start Level Service Specification on page 203. The Start Level service can also be used to query the autostart setting:
• isBundlePersistentlyStarted(Bundle) – false if the bundle’s autostart setting indicates Stopped, otherwise true.
• isBundleActivationPolicyUsed(Bundle) – true if the bundle’s autostart setting indicates that the activation policy declared in the manifest must be used. false if the bundle must be eagerly activated.
Fragment bundles can not be started and must cause a Bundle Exception when there is an attempt to start them.
可選的啟動(dòng)級(jí)別服務(wù)影響了bundles的實(shí)際啟動(dòng)和停止的順序。它也能用來查詢自動(dòng)啟動(dòng)設(shè)置:
• isBundlePersistentlyStarted(Bundle) – 如果bundle的自動(dòng)啟動(dòng)設(shè)置為Stopped,該值為false,否則為true。
• isBundleActivationPolicyUsed(Bundle) – 如果bundle的自動(dòng)啟動(dòng)設(shè)置表示manifest中聲明的激活策略必須被使用,該值為true,如果bundle必須優(yōu)先激活,值為false。
片段bundles不能被啟動(dòng),如果嘗試啟動(dòng)它們必須引起一個(gè)BundleException。
4.3.6 Activation
A bundle is activated by calling its Bundle Activator object, if one exists. The BundleActivator interface defines methods that the Framework invokes when it starts and stops the bundle.To inform the OSGi environment of the fully qualified class name serving as its Bundle Activator, a bundle developer must declare a Bundle-Activator manifest header in the bundle’s manifest file. The Framework must instantiate a new object of this class and cast it to a BundleActivator instance. It must then call the BundleActivator.start method to start the bundle.
The following is an example of a Bundle-Activator manifest header:
一個(gè)bundle通過調(diào)用它的Bundle Activator對象來激活,如果這個(gè)對象存在。接口BundleActivator定義了一些方法,當(dāng)bundle啟動(dòng)時(shí)或停止由框架調(diào)用它們。
為了通知做為全屬性類名的OSGi環(huán)境的服務(wù)的Bundle Activator,bundle開發(fā)者必須聲明頭Bundle-Activator,框架必須實(shí)例化一個(gè)這個(gè)類的對象,并將其cast為一個(gè) BundleActivator的實(shí)例。然后它必須調(diào)用BundleActivator.start方法來啟動(dòng)這個(gè)bundle。
下面是一個(gè)頭Bundle-Activator的例子:
Bundle-Activator: com.acme.Activator
A class acting as a Bundle Activator must implement the BundleActivator interface, be declared public, and have a public default constructor so an instance of it may be created with Class.newInstance.
一個(gè)扮演了Bundle Activator的類必須實(shí)現(xiàn)接口BundleActivator,聲明為public,有一個(gè)public的默認(rèn)構(gòu)造函數(shù),可以通過Class.newInstance來創(chuàng)建一個(gè)它的實(shí)例。
Supplying a Bundle Activator is optional. For example, a library bundle that only exports a number of packages does not need to define a Bundle Activator. In addition, other mechanism exists to obtain control and get a BundleContext, like for example the Service Component Runtime.
提供一個(gè)Bundle Activator是可選的,例如,一個(gè)類庫bundle僅僅輸出一些包,不需要定義Bundle Activator。另外,還有一些其他機(jī)制用于獲取控制權(quán)和獲得一個(gè)BundleContext,例如Service Component Runtime。
The BundleActivator interface defines these methods for starting and stopping a bundle:
• start(BundleContext) – This method can allocate resources that a bundle needs, start threads, register services, and more. If this method does not register any services, the bundle can register services it needs later: for example, in a callback or an external event, as long as it is in the ACTIVE state. If the start(BundleContext) method throws an exception, the Framework must mark the bundle as stopped and send out STOPPING and STOPPED events but it must not call the Bundle Activator stop(BundleContext) method.
• stop(BundleContext) – This method must undo all the actions of the BundleActivator.start(BundleContext) method. However, it is unnecessary to unregister services or Framework listeners, because they must be cleaned up by the Framework anyway.
接口BundleActivator 定義了以下方法,用于啟動(dòng)和停止一個(gè)bundle:
• start(BundleContext) – 這個(gè)方法能夠分派bundle需要的資源,啟動(dòng)線程,注冊服務(wù)等。如果這個(gè)方法不注冊任何方法,可以在后面當(dāng)它需要的時(shí)候再注冊:例如,在一個(gè)回調(diào)或一個(gè) 外部事件中,只要是它處于ACTIVE狀態(tài),都可以注冊服務(wù)。如果這個(gè)方法拋出一個(gè)exception,框架必須標(biāo)記這個(gè)bundle為stopped, 然后發(fā)出STOPPING和STOPPED事件,但是必須不能調(diào)用Bundle Activator的stop(BundleContext)方法
• stop(BundleContext) – 這個(gè)方法必須撤銷BundleActivator.start(BundleContext)方法中的所有行為,但是沒有必要注銷服務(wù)和框架的監(jiān)聽器,因?yàn)樗鼈兪怯煽蚣軄砬謇淼摹?br />
A Bundle Activator must be created when a Bundle is started, implying the creation of a class loader. For larger systems, this greedy strategy can significantly increase startup times and unnecessarily increase the memory footprint. Mechanisms such as the Service Component Runtime and activation policies can mitigate these problems.
Fragment bundles must not have a Bundle Activator specified.
當(dāng)一個(gè)bundle啟動(dòng)的時(shí)候,一個(gè)Bundle Activator必須被創(chuàng)建,也意味著一個(gè)class loader的生成。對于一個(gè)大的系統(tǒng),這種策略會(huì)明顯的增加啟動(dòng)時(shí)間,增加一些不必要的內(nèi)存開銷。Service Component Runtime和激活策略能緩解這個(gè)問題。
4.3.7 Activation Policies
The activation of a bundle can also be deferred to a later time from its start using an activation policy. This policy is specified in the Bundle-ActivationPolicy header with the following syntax:一個(gè)bundle的激活也可以使用一個(gè)激活策略,晚于它的啟動(dòng)時(shí)間。這個(gè)策略指定在頭Bundle-ActivationPolicy中:
Bundle-ActivationPolicy ::= policy ( ’;’ directive )*
policy ::= ’lazy’
policy ::= ’lazy’
The only policy defined is the lazy activation policy. If no Bundle-ActivationPolicy header is specified, the bundle will use eager activation.
這里僅定義了一個(gè)lazy激活策略。如果頭Bundle-ActivationPolicy沒有被指定,bundle將使用優(yōu)先激活。
4.3.7.1 Lazy Activation Policy
A lazy activation policy indicates that the bundle, once started, must not be activated until a class is loaded from it; either during normal class loading or via the Bundle loadClass method. Resource loading does not trigger the activation. This change from the default eager activation policy is reflected in the state of the bundle and its events. When a bundle is started using a lazy activation policy, the following steps must be taken:
• A Bundle Context is created for the bundle.
• The bundle state is moved to the STARTING state.
• The LAZY_ACTIVATION event is fired.
• The system waits for a class load from the bundle to occur.
• The normal STARTING event is fired.
• The bundle is activated.
• The bundle state is moved to ACTIVE.
• The STARTED event is fired.
If the activation fails because the Bundle Activator start method has thrown an exception, the bundle must be stopped without calling the Bundle Activator stop method. These steps are pictured in a flow chart in Figure 4.27. This flow chart also shows the difference in activation policy of the normal eager activation and the lazy activation.
一個(gè)lazy激活策略表示這個(gè)bundle一旦啟動(dòng),必須不能被激活,直到它其中的一個(gè)類被加載,在普通的類加載期間或通過Bundle的 loadClass方法加載。資源的加載不會(huì)觸發(fā)bundle的激活。這個(gè)從默認(rèn)的優(yōu)先激活策略而來的改變被反射在bundle狀態(tài)和它的時(shí)間中。當(dāng)一個(gè) bundle使用lazy激活策略啟動(dòng)時(shí),必須通過以下步驟:
• 這個(gè)bundle的BundleContext被創(chuàng)建。
• bundle的狀態(tài)變?yōu)镾TARTING。
• LAZY_ACTIVATION事件被觸發(fā)。
• 系統(tǒng)等待這個(gè)bundle的類加載的出現(xiàn)(當(dāng)加載它的類的時(shí)候,它才被激活)。
• 事件STARTING被觸發(fā)。
• bundle被激活。
• bundle的狀態(tài)變?yōu)锳CTIVE。
• STARTED事件被觸發(fā)。
如果Bundle Activator方法拋出一個(gè)exception導(dǎo)致激活失敗,bundle必須被停止,但是不調(diào)用Bundle Activator stop方法。

The lazy activation policy allows a Framework implementation to defer the creation of the bundle class loader and activation of the bundle until the bundle is first used; potentially saving resources and initialization time during startup.
By default, any class load can trigger the lazy activation, however, resource loads must not trigger the activation. The lazy activation policy can define which classes cause the activation with the following directives:
• include – A list of package names that must trigger the activation when a class is loaded from any of these packages. The default is all package names present in the bundle.
• exclude – A list of package names that must not trigger the activation of the bundle when a class is loaded from any of these packages. The default is no package names.
For example:
lazy激活策略允許一個(gè)框架實(shí)現(xiàn)延遲bundle的class loader的生成和bundle的激活,直到這個(gè)bundle第一次被使用,通常是在啟動(dòng)時(shí),保存資源和初始化的時(shí)候發(fā)生。
默認(rèn)情況下,加載一個(gè)類會(huì)觸發(fā)lazy激活,但是加載資源必須不能觸發(fā)激活。lazy激活策略能定義以下會(huì)引發(fā)激活的的類:
• include – 包名列表,當(dāng)這個(gè)列表中的任何一個(gè)包中的類被加載,必須觸發(fā)激活。默認(rèn)是bundle中所有的包都會(huì)觸發(fā)。
• exclude – 包名列表,當(dāng)這個(gè)列表中的任何一個(gè)包中的類被加載,必須不能觸發(fā)激活。默認(rèn)是沒有包。
例如:
Bundle-ActivationPolicy: lazy;
include:="com.acme.service.base,com.acme.service.help"
include:="com.acme.service.base,com.acme.service.help"
When a class load triggers the lazy activation, the Framework must first define the triggering class. This definition can trigger additional lazy activations. These activations must be deferred until all transitive class loads and defines have finished. Thereafter, the activations must be executed in the reverse order of detection. That is, the last detected activation must be executed first. Only after all deferred activations are finished must the class load that triggered the activation return with the loaded class. If an error occurs during this process, it should be reported as a Framework ERROR event. However, the class load must succeed normally. A bundle that fails its lazy activation should not be activated again until the framework is restarted or the bundle is explicitly started by calling the Bundle start method.
當(dāng)一個(gè)類加載觸發(fā)lazy激活時(shí),框架必須首先定義這個(gè)觸發(fā)類,這個(gè)定義能觸發(fā)其他的lazy激活。這些激活必須被延遲,知道所有涉及的類加載和定義都完 成,然后,激活必須根據(jù)觸發(fā)的倒序來執(zhí)行。也就是說,最后被檢測到的激活必須首先被執(zhí)行。所有被延遲的激活完成之后,觸發(fā)激活的類加載才返回加載的類的對 象。如果在這個(gè)過程中出現(xiàn)任何錯(cuò)誤,將被報(bào)告為一個(gè)Framework ERROR事件。但是類加載必須正常完成。一個(gè)lazy激活失敗的bundle不應(yīng)該再次被激活,除非框架重啟,或這個(gè)bundle通過調(diào)用Bundle start方法被明確啟動(dòng)。
4.3.8 Stopping Bundles
The Bundle interface defines the stop(int) method for stopping a bundle.This stops a bundle and sets the bundle’s state to RESOLVED. The stop(int) takes an integer option. The following value has been defined for this option:
• 0 – If the bundle was activated, then deactivate the bundle and sets the autostart setting for this bundle to Stopped.
• STOP_TRANSIENT – If the bundle was activated, then deactivate the bundle. Does not alter the autostart setting for this bundle.
Bundle接口為停止一個(gè)bundle定義了方法stop(int)。
它將停止一個(gè)bundle,并把bundle的狀態(tài)設(shè)置為RESOLVED,它有個(gè)整型參數(shù),可以有以下值:
• 0 – 如果這個(gè)bundle處于激活狀態(tài),那么解除激活,設(shè)置自動(dòng)啟動(dòng)設(shè)置為Stopped。
• STOP_TRANSIENT – 如果bundle處于激活狀態(tài),那么解除激活。但是不改變它的自動(dòng)啟動(dòng)設(shè)置。
The stop() method calls stop(0).
調(diào)用stop()相當(dāng)于調(diào)用stop(0)
The optional Start Level service influences the actual order of starting and stopping of bundles. See Start Level Service Specification on page 203.
Attempting to stop a Fragment bundle must result in a Bundle Exception.
嘗試停止一個(gè)片段bundle必須引發(fā)一個(gè)BundleException。
4.3.9 Deactivation
The BundleActivator interface defines a stop(BundleContext) method, which is invoked by the Framework to stop a bundle. This method must release any resources allocated since activation. All threads associated with the stopping bundle should be stopped immediately. The threaded codemay no longer use Framework-related objects (such as services and BundleContext objects) once the stop method returns.
If the stopping bundle had registered any services during its lifetime, then the Framework must automatically unregister all registered services when the bundle is stopped. It is therefore unnecessary to unregister any services in the stop method.
BundleActivator接口定義了一個(gè)stop(BundleContext)方法,它由框架調(diào)用來停止一個(gè)bundle。這個(gè)方法必須釋放所有 激活時(shí)分派的所有資源。關(guān)聯(lián)到這個(gè)即將停止的bundle的所有線程應(yīng)該被立即停止。一旦stop方法返回,線程代碼將不再能使用框架相關(guān)的對象(例如 services 和BundleContext )。
如果這個(gè)即將停止的bundle注冊了任何服務(wù),那么框架必須自動(dòng)注銷這些服務(wù)。因此,沒有必要在stop方法中注銷任何服務(wù)。
The Framework must guarantee that if a BundleActivator.start method has executed successfully, that same BundleActivator object must be called with its BundleActivator.stop method when the bundle is deactivated. After calling the stop method, that particular BundleActivator object must never be used again.
Packages exported by a stopped bundle continue to be available to other bundles. This continued export implies that other bundles can execute code from a stopped bundle, and the designer of a bundle should assure that this is not harmful. Exporting interfaces only is one way to prevent such unwanted execution when the bundle is not started. Generally, to ensure they cannot be executed, interfaces should not contain executable code.
框架必須保證,如果一個(gè)BundleActivator.start方法執(zhí)行成功,那么當(dāng)這個(gè)bundle被解除激活的時(shí)候,必須調(diào)用同一個(gè) BundleActivator對象的BundleActivator.stop方法,stop方法調(diào)用之后,這個(gè)BundleActivator對象將 不會(huì)再使用到。
一個(gè)停止了的bundle輸出的包對其他bundle繼續(xù)有效,這里的繼續(xù)輸出暗指其他bundle可以執(zhí)行一個(gè)停止了的bundle的代碼,一個(gè)bundle的設(shè)計(jì)者應(yīng)該確保這不會(huì)造成危害。通常為了確保他們不能被執(zhí)行,接口應(yīng)該不包含可執(zhí)行代碼。
4.3.10 Updating Bundles
The Bundle interface defines two methods for updating a bundle:• update() – This method updates a bundle.
• update(InputStream) – This method updates a bundle from the specified InputStream object.
The update process supports migration from one version of a bundle to a newer version of the same bundle. The exports of an updated bundle must be immediately available to the Framework. If none of the old exports are used, then the old exports must be removed. Otherwise, all old exports must remain available for existing bundles and future resolves until the refreshPackages method is called or the Framework is restarted.
An updater of a bundle must have AdminPermission[<bundle>,LIFECYCLE] for both the installed bundle as well as the new bundle. The parameters of
接口Bundle定義了2個(gè)方法用于更新一個(gè)bundle:
• update() – 更新一個(gè)bundle
• update(InputStream) – 從指定的InputStream對象更新一個(gè)bundle
更新過程支持從一個(gè)bundle的當(dāng)前版本移植到一個(gè)新版本。一個(gè)更新的bundle的輸出必須立即對框架有效,如果舊版本的輸出沒有被用到,那么輸出將 被移除,否則,所有舊版本的輸出都保持有效。直到PackageAdmin.refreshPackages方法被調(diào)用,或是框架重啟。
AdminPermission are explained in Admin Permission on page 101.
4.3.11 Uninstalling Bundles
The Bundle interface defines the uninstall() method for uninstalling a bundle from the Framework. This method causes the Framework to notify other bundles that the bundle is being uninstalled, and sets the bundle’s state to UNINSTALLED. To whatever extent possible, the Framework must remove any resources related to the bundle. This method must always uninstall thebundle from the persistent storage of the Framework.
接口Bundle定義了uninstall()方法用于從框架中卸載一個(gè)bundle。這個(gè)方法會(huì)引起框架通知其他bundles,這個(gè)bundle正在 被卸載,并設(shè)置這個(gè)bundle的狀態(tài)為UNINSTALLED。不論這個(gè)bundle關(guān)聯(lián)到哪,框架必須刪除與這個(gè)bundle相關(guān)的所有資源。這個(gè)方 法從框架的持久存儲(chǔ)中卸載這個(gè)bundle。
Once this method returns, the state of the OSGi Service Platform must be the same as if the bundle had never been installed, unless:
• The uninstalled bundle has exported any packages (via its Export-Package manifest header)
• The uninstalled bundle was selected by the Framework as the exporter of these packages.
一旦這個(gè)方法返回,OSGi服務(wù)平臺(tái)的狀態(tài)必須與從未安裝這個(gè)bundle的狀態(tài)一致,除非:
• 這個(gè)被卸載的bundle輸出的有包(通過頭Export-Package)。
• 這個(gè)被卸載的bundle被框架選擇為這些包的輸出者。
If none of the old exports are used, then the old exports must be removed. Otherwise, all old exports must remain available for existing bundles and future resolves until the refreshPackages method is called or the Framework is restarted.
如果輸出沒有被使用,那么它們必須被移除,否則如果有輸出被使用,那么所有的輸出必須對其他已經(jīng)存在的bundle和將要解析的bundle可用,直到refreshPackages方法被調(diào)用,或框架重啟。
4.3.12 Detecting Bundle Changes
The Bundle object provides a convenient way to detect changes in a bundle.The Framework must keep the time that a bundle is changed by any of the life cycle operations. The getLastModified() method will return the last time the bundle was installed, updated, or uninstalled. This last modified time must be stored persistently.
The method must return the number of milliseconds since midnight Jan. 1, 1970 UTC with the condition that a change must always result in a higher value than the previous last modified time of any bundle.
The getLastModified() is very useful when a bundle is caching resources from another bundle and needs to refresh the cache when the bundle changes. This life cycle change of the target bundle can happen while the caching bundle is not active. The last modified time is therefore a convenient way to track these target bundles.
Bundle對象提供了一個(gè)方便的方法去檢測一個(gè)bundle的改變。
框架必須保持一個(gè)bundle被其生命周期操作所做的改變的次數(shù),方法getLastModified()將返回這個(gè)bundle被安裝,更新或卸載后所做的最后一次改變。最后修改時(shí)間必須被持久保存。
這個(gè)方法必須返回從Jan. 1, 1970 UTC晚上12點(diǎn)到現(xiàn)在的毫秒數(shù),這個(gè)毫秒數(shù)的每次改變都要大于上一次修改的時(shí)間。
當(dāng)一個(gè)bundle緩存其他bundle的資源時(shí),當(dāng)它改變時(shí)需要刷新緩存,方法getLastModified()將非常有用。目標(biāo)bundle的生命周期變化可以在緩存bundle不活躍時(shí)發(fā)生,因此最后修改時(shí)間可以方便的跟蹤這些目標(biāo)bundles。
4.3.13 Retrieving Manifest Headers
The Bundle interface defines two methods to return manifest header information: getHeaders() and getHeaders(String).• getHeaders() – Returns a Dictionary object that contains the bundle's manifest headers and values as key/value pairs. The values returned are localized according to the default locale returned by java.util.Locale.getDefault.
• getHeaders(String) – Returns a Dictionary object that contains the bundle's manifest headers and values as key/value pairs. The returned values are localized using the specified locale. The locale may take the following values:
• null – The default locale returned by java.util.Locale.getDefault is used. This makes this method identical to the getHeaders() method.
• Empty string – The dictionary will contain the raw (unlocalized) manifest headers including any leading '%'.
• A Specific Locale – The given locale is used to localize the manifest headers..
Bundle接口定義了2個(gè)方法用于返回manifest頭信息:getHeaders()和 getHeaders(String)。
• getHeaders() – 返回一個(gè)Dictionary對象,包含了bundle的manifest頭的鍵/值對。返回的值根據(jù)java.util.Locale.getDefault返回的默認(rèn)locale來進(jìn)行本地化。
• getHeaders(String) – 返回一個(gè)Dictionary 對象,包含了bundle的manifest頭的鍵/值對。返回的值使用指定的locale來進(jìn)行本地化,這個(gè)locale可以是以下值:
• null – 由java.util.Locale.getDefault返回的默認(rèn)locale,將使這個(gè)方法與getHeaders()方法一樣。
• Empty string – dictionary將包含未本地化的行,manifest頭,包括'%'(參見本地化那節(jié))
• A Specific Locale – 給定的locale被用來本地化manifest頭。
Localization is performed according to the description in Localization on page 62. If no translation is found for a specific key, the Dictionary returned by Bundle.getHeaders will return the raw values as specified in the manifest header values without the leading '%’ character.
These methods require AdminPermission[<bundle>, METADATA] because some of the manifest header information may be sensitive, such as the packages listed in the Export-Package header. Bundles always have permission to read their own headers.
The getHeaders methods must continue to provide the manifest header information after the bundle enters the UNINSTALLED state. After the bundle has been uninstalled, this method will only return manifest headers that are raw or localized for the default locale at the time the bundle was uninstalled. A framework implementation must use only the raw (unlocalized) manifest headers when processing manifest headers. Localizations must not influence the operations of the Framework.
如果一個(gè)指定的key沒有譯文,Bundle.getHeaders返回的Dictionary對象將返回指定在manifest中的值,不包含'%'。
這2個(gè)方法需要AdminPermission[<bundle>, METADATA],因?yàn)橛行╊^信息是很敏感的,例如Export-Package中的包列表,Bundle對象總是有讀取他們自己的頭的權(quán)限。
bundle進(jìn)入U(xiǎn)NINSTALLED狀態(tài)后,getHeaders方法必須繼續(xù)提供頭信息。bundle被卸載之后,這個(gè)方法僅僅返回頭的原始數(shù)據(jù)或默認(rèn)locale的本地化值。一個(gè)框架實(shí)現(xiàn)在處理頭的時(shí)候必須只能使用原始頭,本地化必須不能影響框架的操作。
4.3.14 Loading Classes
In certain cases, it is necessary to load classes as if they were loaded from inside the bundle. The loadClass(String) method gives access to the bundle class loader. This method can be used to:• Load plugins from another bundle
• Start an application model activator
• Interact with legacy code
在某些情況下,有必要像bundle內(nèi)部加載類一樣的加載某些類,loadClass(String)方法可以訪問bundle的class loader。它可以用來:
• 加載另外一個(gè)bundle的插件
• 啟動(dòng)一個(gè)應(yīng)用程序模型的activator
• 與遺留代碼整合
For example, an application model could use this feature to load the initial class from the bundle and start it according to the rules of the application model.
例如,一個(gè)應(yīng)用程序模型可以使用這個(gè)特性去加載一個(gè)bundle的初始化類,并根據(jù)這個(gè)模型的規(guī)則啟動(dòng)它。
void appStart() {
Class initializer = bundle.loadClass(activator);
if ( initializer != null ) {
App app = (App) initializer.newInstance();
app.activate();
}
}
Class initializer = bundle.loadClass(activator);
if ( initializer != null ) {
App app = (App) initializer.newInstance();
app.activate();
}
}
Loading a class from a bundle can cause it to be activated if the bundle uses a lazy activation policy.
加載一個(gè)bundle的類會(huì)激活這個(gè)bundle,如果這個(gè)bundle使用了lazy激活策略。
4.3.15 Access to Resources
The resources from a bundle can come from different sources. They can come from the raw JAR file, Fragment bundles, imported packages, or the bundle class path. Different use cases require a different resource search strategy. The Bundle interface provides a number of methods that access resources but use different strategies. The following search strategies are supported:一個(gè)bundle中的資源可以來自不同的源,它們可以來自原始JAR文件,片段bundles,引入的包,或是bundle的類路徑。不同的來源需要不同資源查找策略。接口Bundle提供了很多方法,用于訪問這些資源,但是使用的是不同的策略。支持一下策略:
• Class Space – The getResource(String) and getResources(String) provide access to resources that is consistent with the class space as described in Overall Search Order on page 52. Following the search order can make certain parts of the JAR files inaccessible. These methods
require that the bundle is resolved. If the bundle is not resolved, the Framework must attempt to resolve it.
The search order can hide certain directories of the JAR file. Split packages are taken into account; therefore, resources with the same package names can come from different JARs. If the bundle is unresolved (or cannot be resolved), the getResource and getResources methods must only load resources from the bundle class path. This search strategy should be used by code that wants to access its own resources. Calling either method can cause the creation of a class loader and force the bundle to become resolved.
• Class Space – getResource(String)和getResources(String)方法提供了對資源的訪問,這個(gè)資源與52頁中Overall Search Order描述的類空間資源是一致的。按照這個(gè)查找順序可能會(huì)使JAR文件的某些部分不可訪問。這2個(gè)方法需要bundle被解析,如果bundle沒有 被解析,框架必須嘗試解析它。
這個(gè)查找順序能隱藏JAR文件的某些目錄,split包需要被考慮進(jìn)去,因此,具有相同包名的資源可以來自不同的JAR文件。如果bundle沒有被解析 (或不能被解析),getResource 和getResources 方法必須只能從bundle的類路徑中加載資源。這個(gè)查找策略應(yīng)該被用于訪問自己的資源的代碼。調(diào)用其中一個(gè)方法能引起一個(gè)class loader的生成,并使bundle被解析。
• JAR File – The getEntry(String) and getEntryPaths(String) methods provide access to the resources in the bundle’s JAR file. No searching is involved, only the raw JAR file is taken into account. The purpose of these methods is to provide low-level access without requiring that the bundle is resolved.
• JAR File – 方法getEntry(String)和getEntryPaths(String)提供了對bundle的JAR文件中的資源的訪問。不包含任何查找,僅僅涉及原始JAR文件,這2個(gè)方法的目的是提供低級(jí)別的訪問,不需要bundle被解析。
• Bundle Space – The findEntries(String,String,boolean) is an intermediate form. Useful when configuration or setup information is needed from another bundle. It considers Fragment bundles but it must never create a class loader. The method provides access to all directories in the associated JAR files.
• Bundle Space – findEntries(String,String,boolean)方法是一個(gè)媒介形態(tài),當(dāng)需要其他bundle的配置或設(shè)置信息時(shí)會(huì)很有用,這個(gè) bundle可以被認(rèn)為是片段bundle,但是必須不能創(chuàng)建一個(gè)class loader,這個(gè)方法提供了對象關(guān)聯(lián)的JAR文件的全目錄訪問。
For example, consider the following setup:
A: Require-Bundle: D
Import-Package: q,t
Export-Package: t
B: Export-Package: q,t
C: Fragment-Host: A
D: Export-Package: s
This setup is depicted in Figure 4.28.

The following table shows the effect of getting a resource from this setup when bundle A is resolved.
Table 4.5 Differences between getResource, getEntry, and findEntries for resolved bundle A
Resource | getResource | getEntry | findEntries |
q | B.q | null | null |
p | A.p > C.p | A.p | A.p > C.p |
r | C.r | null | C.r |
s | D.s | null | null |
t | B.t | A.t | A.t |
Table 4.6 shows the same cases as the previous table but now for an unresolved bundle A.
Table 4.6 Differences between getResource, getEntry, and findEntries for an unresolved bundle A
Resource | getResource | getEntry | findEntries |
q | null | null | null |
p | A.p | A.p | A.p |
r | null | null | null |
s | null | null | null |
t | A.t | A.t | A.t |
4.3.16 Permissions of a Bundle
The Bundle interface defines a method for returning information pertaining to a bundle’s permissions: hasPermission(Object). This method returns true if the bundle’s Protection Domain has the specified permission, and false if it does not, or if the object specified by the argument is not an instance of java.security.Permission.The parameter type is Object so that the Framework can be implemented on Java platforms that do not support Java 2 based security.
Bundle接口定義了一個(gè)方法,用于返回適合一個(gè)bundle的權(quán)限的信息:hasPermission(Object)。如果bundle的保護(hù)域有 指定的權(quán)限,該方法返回true,否則返回false,或者如果參數(shù)指定的object不是java.security.Permission的實(shí)例,也 返回false。
4.3.17 Access to a Bundle’s Bundle Context
Bundles that have been started have a Bundle Context. This object is a capability; it is intended to be used only by the bundle. However, there are a number of cases where bundles must act on behalf of other bundles. For example, the Service Component Runtime registers services on behalf of other bundles. The framework therefore provides access to another bundle’s context via the getBundleContext() method. If there is no Bundle Context for that Bundle because the bundle is a fragment bundle or the bundle state is not in { STARTING, ACTIVE, STOPPING }, then null must be returned.This method is potentially harmful because it allows any bundle to act as any other bundle. In a secure system, the method is protected by requiring AdminPermission[*,CONTEXT].
被啟動(dòng)的bundles都會(huì)有一個(gè)BundleContext,這個(gè)對象是一個(gè)只能被bundle使用的功能對象。但是有很多情況下,bundles必須 扮演成另外的bundles,例如,Service Component Runtime注冊服務(wù)就扮演著其他bundle。因此框架必須通過getBundleContext()方法提供對別的bundle的context的 訪問。如果一個(gè)bundle沒有BundleContext,必須是因?yàn)樗且粋€(gè)片段bundle或它的狀態(tài)不是 STARTING,ACTIVE,STOPING,這時(shí)這個(gè)方法必須返回null。
這個(gè)方法有一定的潛在危險(xiǎn),因?yàn)樗试Sbundle扮演成其他任何bundle。在一個(gè)安全系統(tǒng),需要AdminPermission[*,CONTEXT]來保護(hù)這個(gè)方法。
4.4 The Bundle Context
The relationship between the Framework and its installed bundles is realized by the use of BundleContext objects. A BundleContext object represents the execution context of a single bundle within the OSGi Service Platform, and acts as a proxy to the underlying Framework.框架和安裝的bundle之間的聯(lián)系是通過使用BundleContext對象來搭建的,一個(gè)BundleContext對象是平臺(tái)中的一個(gè)bundle的執(zhí)行上下文,它扮演底層框架的代理。
A BundleContext object is created by the Framework when a bundle is started. The bundle can use this private BundleContext object for the following purposes:
• Installing new bundles into the OSGi environment. See Installing Bundles on page 82.
• Interrogating other bundles installed in the OSGi environment. See Getting Bundle Information on page 93.
• Obtaining a persistent storage area. See Persistent Storage on page 93.
• Retrieving service objects of registered services. See Service References on page 109.
• Registering services in the Framework service. See Registering Services on page 110.
• Subscribing or unsubscribing to events broadcast by the Framework. See Listeners on page 97.
一個(gè)BundleContext是當(dāng)bundle啟動(dòng)的時(shí)候由框架生成的。這個(gè)bundle可以使用它的私有的BundleContext 對象實(shí)現(xiàn)以下功能:
• 安裝新bundle。
• 查詢其他已經(jīng)安裝的bundles
• 獲得一個(gè)持久存儲(chǔ)區(qū)域(參見JavaDoc:
getDataFile(java.lang.String filename)
)• 獲取一個(gè)注冊了的服務(wù)
• 注冊一個(gè)服務(wù)到框架服務(wù)中
• 訂閱或退訂框架的時(shí)間廣播。
When a bundle is started, the Framework creates a BundleContext object and provides this object as an argument to the start(BundleContext) method of the bundle’s Bundle Activator. Each bundle is provided with its own BundleContext object; these objects should not be passed between bundles, since the BundleContext object is related to the security and resource
allocation aspects of a bundle.
After the stop(BundleContext) method has returned, the BundleContext object must no longer be used. Framework implementations must throw an exception if the BundleContext object is used after a bundle is stopped.
當(dāng)一個(gè)bundle啟動(dòng)時(shí),框架生成一個(gè)BundleContext對象,并將它作為參數(shù)提供給bundle的BundleActivator的 start(BundleContext)方法。每個(gè)bundle都有它自己的BundleContext對象,這些對象不能在bundles間相互傳 遞,因?yàn)檫@個(gè)BundleContext對象關(guān)系到一個(gè)bundle的安全方面和資源分配。
stop(BundleContext)方法返回后,BundleContext對象必須不再能使用。如果使用一個(gè)停止了的bundle的BundleContext,框架必須拋出一個(gè)exception。
4.4.1 Getting Bundle Information
The BundleContext interface defines methods to retrieve information about bundles installed in the OSGi Service Platform:• getBundle() – Returns the single Bundle object associated with the BundleContext object.
• getBundles() – Returns an array of the bundles currently installed in the Framework.
• getBundle(long) – Returns the Bundle object specified by the unique identifier, or null if no matching bundle is found.
Bundle access is not restricted; any bundle can enumerate the set of installed bundles. Information that can identify a bundle, however (such as its location, or its header information), is only provided to callers that have AdminPermission[<bundle>,METADATA].
接口BundleContext定義了一些方法,用于獲取安裝在平臺(tái)中的bundles的信息:
• getBundle() – 返回與當(dāng)前BundleContext相關(guān)聯(lián)的Bundle對象。
• getBundles() – 返回當(dāng)前安裝在框架中的bundles集合
• getBundle(long) – 返回具有指定的唯一標(biāo)識(shí)符的bundle對象,如果沒有找到匹配的bundle,返回null
bundle的訪問是不受限制的,任何bundle都可以列舉已經(jīng)安裝了的bundles的集合,和可以識(shí)別bundle的信息,例如它的路徑,它的頭信息,但是訪問者必須要有AdminPermission[<bundle>,METADATA]權(quán)限。
4.4.2 Persistent Storage
The Framework should provide a private persistent storage area for each installed bundle on platforms with some form of file system support.框架應(yīng)該為每一個(gè)已經(jīng)安裝了的bundle提供一個(gè)私有的持久存儲(chǔ)區(qū)域,這個(gè)區(qū)域是操作系統(tǒng)支持的文件結(jié)構(gòu)。
The BundleContext interface defines access to this storage in terms of the File class, which supports platform-independent definitions of file and directory names.
BundleContext 接口根據(jù)類File定義對這個(gè)存儲(chǔ)區(qū)域的訪問,它支持具有平臺(tái)依賴的文件名和目錄名。
The BundleContext interface defines a method to access the private persistent storage area: getDataFile(String). This method takes a relative file name as an argument. It translates this file name into an absolute file name in the bundle’s persistent storage area. It then returns a File object. This method returns null if there is no support for persistent storage.The Framework must automatically provide the bundle with FilePermission[<storage area>, READ | WRITE | DELETE] to allow the bundle to read, write, and delete files in that storage area.
接口BundleContext 定義了一個(gè)方法用于訪問私有持久存儲(chǔ)區(qū)域:getDataFile(String),文件名作為參數(shù),它將這個(gè)文件名轉(zhuǎn)換成bundle的持久存儲(chǔ)區(qū)域中 的絕對路徑文件名,然后返回這個(gè)File對象,如果沒有持久存儲(chǔ)支持,將返回null。框架必須自動(dòng)給bundle提供 FilePermission[<storage area>, READ | WRITE | DELETE]權(quán)限,以便這個(gè)bundle能讀,寫,刪除存儲(chǔ)區(qū)域中的文件。
If EXECUTE permissions is required, then a relative path name can be used in the File Permission definition. For example, FilePermission[bin/*, EXECUTE] specifies that the sub-directory in the bundle’s private data area may contain executables. This only provides execute permission within the Java environment and does not handle the potential underlying operating system issues related to executables.
This special treatment applies only to FilePermission objects assigned to a bundle. Default permissions must not receive this special treatment. A FilePermission for a relative path name assigned via the setDefaultPermission method must be ignored.
如果需要執(zhí)行權(quán)限,那么一個(gè)相對路徑名字可以被用于文件權(quán)限定義,例如,F(xiàn)ilePermission[bin/*, EXECUTE]指定bundle的私有數(shù)據(jù)區(qū)域的子目錄可能包含可執(zhí)行文件。這僅僅只提供java環(huán)境中的執(zhí)行權(quán)限,不會(huì)處理執(zhí)行文件潛在的操作系統(tǒng)問 題。
這個(gè)特殊的處理僅僅用于分派給一個(gè)bundle的文件權(quán)限對象,默認(rèn)的權(quán)限不受影響,一個(gè)通過setDefaultPermission指派的相對路徑名字的文件權(quán)限必須不能被忽略。
4.4.3 Environment Properties
The BundleContext interface defines a method for returning information pertaining to Framework properties: getProperty(String). This method can be used to return the following Framework properties:All Framework properties may be defined by the Operator as System properties. If these properties are not defined as System properties, the Framework must construct these properties from relevant standard Java System properties.
接口BundleContext定義了一個(gè)用于返回屬于框架屬性信息的方法:properties: getProperty(String),這個(gè)方法能夠返回以下屬性信息:
所有的框架屬性可能由操作人員定義為系統(tǒng)屬性,如果這些屬性沒有定義為系統(tǒng)屬性,框架必須從相關(guān)的標(biāo)準(zhǔn)JAVA系統(tǒng)屬性構(gòu)造這些屬性。
屬性列表略.....
4.5 The System Bundle
In addition to normal bundles, the Framework itself is represented as a bundle. The bundle representing the Framework is referred to as the system bundle. Through the system bundle, the Framework may register services that can be used by other bundles. Examples of such services are the Package Admin and Permission Admin services.The system bundle is listed in the set of installed bundles returned by BundleContext.getBundles(), although it differs from other bundles in the following ways:
除了普通的bundle,框架本身也可以看成是一個(gè)bundle,框架bundle被引用為系統(tǒng)bundle。通過系統(tǒng)bundle,框架可以注冊服務(wù)供其他bundle使用,例如 Package Admin和Permission Admin services。
系統(tǒng)bundle被列在由BundleContext.getBundles()返回的安裝bundles集合中,盡管它與其他bundles有以下區(qū)別:
• The system bundle is always assigned a bundle identifier of zero (0).
• 系統(tǒng)bundle的標(biāo)識(shí)符(ID)總是被分派為0.
• The system bundle getLocation method returns the string: "System Bundle", as defined in the Constants interface.
• 系統(tǒng)bundle的getLocation 方法返回字符串"System Bundle",定義在Constants接口中
• The system bundle has a bundle symbolic name that is unique for a specific version. However, the name system.bundle must be recognized as an alias to this implementation-defined name.
• 系統(tǒng)bundle的每一個(gè)版本都有一個(gè)唯一的bundle標(biāo)記名,但是,system.bundle必須被公認(rèn)為這個(gè)由框架定義的bundle名字的別名。
• The system bundle’s life cycle cannot be managed like normal bundles. Its life cycle methods must behave as follows:
• 系統(tǒng)bundle的生命周期不能像普通bundle那樣管理,它的生命周期方法必須表現(xiàn)為以下幾點(diǎn):
• start – Does nothing because the system bundle is already started.
• stop – Returns immediately and shuts down the Framework on another thread.
• update – Returns immediately, then stops and restarts the Framework on another thread.
• uninstall – The Framework must throw a BundleException indicating that the system bundle cannot be uninstalled.
• See Framework Startup and Shutdown on page 100 for more information about the starting and stopping of the Framework.
• The system bundle’s Bundle.getHeaders method returns a Dictionary object with implementation-specific manifest headers. For example, the system bundle’s manifest file should contain an Export-Package header declaring which packages are to be exported by the Framework (for example, org.osgi.framework).
4.6 Events
The OSGi Framework Life Cycle layer supports the following types of events:• BundleEvent – Reports changes in the life cycle of bundles.
• FrameworkEvent – Reports that the Framework is started, start level has changed, packages have been refreshed, or that an error has been encountered.
The actual event that is reported is available with the getType method. The integer that is returned from this method can be one of the constant names that are described in the class. However, events can, and will be, extended in the future. Unrecognized event types should be ignored.
框架生命周期層支持一下時(shí)間類型:
• BundleEvent – 報(bào)告bundles的生命周期的變化
• FrameworkEvent – 報(bào)告框架啟動(dòng),啟動(dòng)級(jí)別被修改,包被刷新,或是遇到的錯(cuò)誤。
被報(bào)告的具體事件可以使用getType方法來獲取,這個(gè)方法返回的整數(shù)是類中描述的恒量名字中的一個(gè)。但是,事件可以(在以后的版本中將)被擴(kuò)展,自定義事件類型應(yīng)該被忽略。
4.6.1 Listeners
A listener interface is associated with each type of event. The following list describes these listeners.一個(gè)監(jiān)聽器接口關(guān)聯(lián)著事件的每個(gè)類型。以下列表描述了這些監(jiān)聽器
• BundleListener and SynchronousBundleListener – Called with an event of type BundleEvent when a bundle’s life cycle information has been changed.
SynchronousBundleListener objects are called synchronously during the processing of the event and must be called before any BundleListener object is called. The following events are sent by the Framework after it has moved to a different state:
當(dāng)一個(gè)bundle的生命周期信息被改變的時(shí)候被調(diào)用,并伴隨一個(gè)類型為BundleEvent的事件。 SynchronousBundleListener對象在處理事件期間被同步調(diào)用,必須在任何BundleListener對象調(diào)用之前調(diào)用它,以下事 件將在bundle的狀態(tài)發(fā)生改變時(shí)由框架發(fā)送出去:
• INSTALLED – Sent after a bundle is installed. The state is now Bundle.INSTALLED state.
• RESOLVED– Sent when the Framework has resolved a bundle. The state is now the Bundle RESOLVED state.
• LAZY_ACTIVATION – The bundle has specified an activation policy; its activation is deferred to a later point in time. The state is set to the Bundle.STARTING state. This is only sent to SynchronousBundleListener objects.
• LAZY_ACTIVATION – bundle被指定了一個(gè)lazy激活策略;它的激活將被延遲到后面的時(shí)間點(diǎn)上,狀態(tài)被設(shè)置為STARTING,因?yàn)長AZY_ACTIVATION不可 以被發(fā)送到監(jiān)聽器,只能被發(fā)送到SynchronousBundleListener 對象(參見API)。
• STARTING – Sent when the Framework is about to activate a bundle. This is only sent to SynchronousBundleListener objects. The state is now the Bundle.STARTING state.
• STARTED – Sent when the Framework has started a bundle. The state is now the Bundle.ACTIVE state.
• STOPPING – Sent when the Framework is about to stop a bundle or the start method of the Bundle Activator has thrown an exception and the bundle is stopped. This event indicates that the Bundle Context will be destroyed. This event is only sent to SynchronousBundleListener objects.
• STOPPED– Sent when the Framework has stopped a bundle.
• UNINSTALLED – Sent when the Framework has uninstalled a bundle
• UNRESOLVED – Sent when the Framework detects that a bundle becomes unresolved; this could happen when the bundle is refreshed or updated. When a set of bundles are refreshed using the Package Admin API then each bundle in the set must have an UNRESOLVED BundleEvent published. The UNRESOLVED BundleEvent must be published after all the bundles in the set have been stopped and, in the case of a synchronous bundle listener, before any of the bundles in the set are re-started. RESOLVED and UNRESOLVED do not have to paired.
• UPDATED – Sent after a bundle is updated.
• FrameworkListener – Called with an event of type FrameworkEvent. Framework events are of type:
• ERROR – Important error that requires the immediate attention of an operator.
• INFO – General information that is of interest in special situations.
• PACKAGES_REFRESHED – The Framework has refreshed the packages.
• STARTED – The Framework has performed all initialization and is running in normal mode.
• STARTLEVEL_CHANGED – Is sent by the Framework after a new start level has been set and processed.
• WARNING – A warning to the operator that is not crucial but may indicate a potential error situation.
BundleContext interface methods are defined which can be used to add and remove each type of listener.
BundleContext接口定義了可以用來添加和刪除監(jiān)聽器的每個(gè)類型的方法。
Events can be asynchronously delivered, unless otherwise stated, meaning that they are not necessarily delivered by the same thread that generated the event. The thread used to call an event listener is not defined.
The Framework must publish a FrameworkEvent.ERROR if a callback to an event listener generates an unchecked exception - except when the callback happens while delivering a FrameworkEvent.ERROR (to prevent an infinite loop).
事件可以被同步發(fā)送,除非特殊說明,也就是說事件不一定要在生成他們的線程中發(fā)送,但是沒有定義用于調(diào)用一個(gè)事件監(jiān)聽器的線程。
如果一個(gè)回調(diào)事件監(jiān)聽器生產(chǎn)生了一個(gè)未檢查的exception,框架必須發(fā)布一個(gè)FrameworkEvent.ERROR - 除非回調(diào)時(shí)當(dāng)時(shí)正在發(fā)布一個(gè)FrameworkEvent.ERROR(為了防止一個(gè)無限循環(huán)[問:這里的無限循環(huán)從何而來?])。
4.6.2 Delivering Events
If the Framework delivers an event asynchronously, it must:• Collect a snapshot of the listener list at the time the event is published (rather than doing so in the future just prior to event delivery), but before the event is delivered, so that listeners do not enter the list after the event happened.
• Ensure, at the time the snapshot is taken, that listeners on the list still belong to active bundles at the time the event is delivered.
• It is possible to use more than one thread to deliver events. If this is the case then each handler must receive the events in the same order as the events were posted. This ensures that handlers see events in the expected order.
如果框架同步發(fā)送事件,它必須:
• 在事件發(fā)布前收集一個(gè)監(jiān)聽器列表的快照(而不是優(yōu)先發(fā)布事件),但是這是在事件發(fā)布之前,所以事件發(fā)生后(事件發(fā)布前),監(jiān)聽器并沒有進(jìn)入這個(gè)列表。
• 確保在快照收集好后,列表中的監(jiān)聽器在事件發(fā)布時(shí)仍然屬于激活的bundles。
• 可以使用多個(gè)線程發(fā)布事件,如果是這樣,各個(gè)handler接收事件的順序必須與事件被提交的順序一致,這確保了handlers能根據(jù)它希望的順序來接收事件。
If the Framework did not capture the current listener list when the event was published, but instead waited until just prior to event delivery, then the following error could occur: a bundle could have started and registered a listener, and then the bundle could see its own BundleEvent.INSTALLED event.
當(dāng)事件發(fā)布時(shí),如果框架沒有捕獲當(dāng)前監(jiān)聽器列表,而是等待事件發(fā)布,應(yīng)該出現(xiàn)以下錯(cuò)誤:一個(gè)bundle被啟動(dòng)并注冊了一個(gè)監(jiān)聽器,那么這個(gè)bundle可以看見它自己的BundleEvent.INSTALLED事件。
The following three scenarios illustrate this concept.
1. Scenario one event sequence:
• Event A is published. 事件A被發(fā)布
• Listener 1 is registered. 監(jiān)聽器1被注冊
• Asynchronous delivery of Event A is attempted. 嘗試同步發(fā)布事件A。
Expected Behavior: Listener 1 must not receive Event A, because it was not registered at the time the event was published.監(jiān)聽器1必須不能收到事件A。
2. Scenario two event sequence:
• Listener 2 is registered. 監(jiān)聽器2被注冊
• Event B is published. 事件B被發(fā)布
• Listener 2 is unregistered.監(jiān)聽器2被注銷
• Asynchronous delivery of Event B is attempted. 嘗試同步發(fā)布事件B。
Expected Behavior: Listener 2 receives Event B, because Listener 2 was registered at the time Event B was published.監(jiān)聽器2可以收到事件B
3. Scenario three event sequence:
• Listener 3 is registered.
• Event C is published.
• The bundle that registered Listener 3 is stopped.
• Asynchronous delivery of Event C is attempted.
Expected Behavior: Listener 3 must not receive Event C, because its Bundle Context object is invalid.
4.6.3 Synchronization Pitfalls
Generally, a bundle that calls a listener should not hold any Java monitors. This means that neither the Framework nor the originator of a synchronous event should be in a monitor when a callback is initiated.通常,調(diào)用一個(gè)監(jiān)聽器的bundle不應(yīng)該持有任何Java監(jiān)視器,意思是說,當(dāng)回調(diào)發(fā)生時(shí),框架和同步事件創(chuàng)造者都不應(yīng)該在一個(gè)監(jiān)視器中。
The purpose of a Java monitor is to protect the update of data structures. This should be a small region of code that does not call any code the effect of which cannot be overseen. Calling the OSGi Framework from synchronized code can cause unexpected side effects. One of these side effects might be deadlock. A deadlock is the situation where two threads are blocked because
they are waiting for each other.
一個(gè)Java監(jiān)視器的目的是為了保護(hù)數(shù)據(jù)結(jié)構(gòu)的更新,這應(yīng)該是一個(gè)很小的代碼區(qū)域,不調(diào)用任何不能具備監(jiān)視效果的代碼。從同步代碼調(diào)用OSGi框架會(huì)引起意想不到的負(fù)面效果,其中一個(gè)負(fù)面效果可能是死鎖。
Time-outs can be used to break deadlocks, but Java monitors do not have time-outs. Therefore, the code will hang forever until the system is reset (Java has deprecated all methods that can stop a thread). This type of deadlock is prevented by not calling the Framework (or other code that might cause callbacks) in a synchronized block.
Time-outs(超時(shí))能用來打破死鎖,但是Java監(jiān)視器沒有time-outs,因此,這些代碼將被永久懸掛直到系統(tǒng)重啟(Java已經(jīng)deprecated所有能停止一個(gè)線程的方法),防止這種死鎖只能是不要再一個(gè)同步塊中調(diào)用框架。
If locks are necessary when calling other code, use the Java monitor to create semaphores that can time-out and thus provide an opportunity to escape a deadlocked situation.
4.7 Framework Startup and Shutdown
A Framework implementation must be started before any services can be provided. How a Framework should be started by the Operator is not detailed in this specification because it can differ for different implementations. Some Framework implementations may provide command line options, and others may read startup information from a configuration file. In all cases, Framework implementations must perform all of the following actions in the given order.一個(gè)框架實(shí)現(xiàn),必須在提供任何服務(wù)之前被啟動(dòng),一個(gè)框架如何由一個(gè)操作員啟動(dòng)并沒有定義在這個(gè)規(guī)范中,因?yàn)樗鼤?huì)因?yàn)閷?shí)現(xiàn)的不同而不同。一些框架實(shí)現(xiàn)可能提供命令行選項(xiàng),其它的可能會(huì)通過一個(gè)配置文件讀取啟動(dòng)信息,總的來說,框架實(shí)現(xiàn)必須以相應(yīng)的順序執(zhí)行以下所有的動(dòng)作
4.7.1 Startup
When the Framework is started, the following actions must occur:當(dāng)框架啟動(dòng)時(shí),必須出現(xiàn)以下動(dòng)作:
1. Event handling is enabled. Events can now be delivered to listeners. Events are discussed in Events on page 97.
2. The system bundle enters the STARTING state. More information about the system bundle can be found in The System Bundle on page 96.
3. All installed bundles previously recorded as being started must be started as described in the Bundle.start method. Any exceptions that occur during startup must be wrapped in a BundleException and then published as a Framework event of type FrameworkEvent.ERROR. Bundles
and their different states are discussed in The Bundle Object on page 81. If the Framework implements the optional Start Level specification, this behavior is different. See Start Level Service Specification on page 203. Any bundles that specify an activation policy must be treated according to their activation policy, see Activation Policies on page 85.
4. The system bundle enters the ACTIVE state.
5. A Framework event of type FrameworkEvent.STARTED is broadcast.
1. 事件處理被啟用,現(xiàn)在事件可以被傳達(dá)給監(jiān)聽器
2. 系統(tǒng)bundle進(jìn)入STARTING狀態(tài)。
3. 所有被記錄為started的以前安裝了的bundle必須根據(jù)Bundle.start來啟動(dòng),啟動(dòng)時(shí),任何exceptions必須被包裝為一個(gè) BundleException并發(fā)布為一個(gè)框架事件,類型為FrameworkEvent.ERROR。如果框架實(shí)現(xiàn)了可選的啟動(dòng)級(jí)別規(guī)范,這個(gè)行為將 有所區(qū)別,任何指定了激活策略的bundle必須根據(jù)它們的激活策略來對待。
4. 系統(tǒng)bundle進(jìn)入ACTIVE狀態(tài)
5. 一個(gè)類型為FrameworkEvent.STARTED的框架時(shí)間被發(fā)布出去。
4.7.2 Shutdown
The Framework will also need to be shut down on occasion. Shutdown can also be initiated by stopping the system bundle, covered in The System Bundle on page 96. When the Framework is shut down, the following actions must occur in the given order:1. The system bundle enters the STOPPING state.
2. All ACTIVE bundles are stopped as described in the Bundle.stop method,except that their persistently recorded state indicates that they must be restarted when the Framework is next started is kept unchanged. Any exceptions that occur during shutdown must be wrapped in a
BundleException and then published as a Framework event of type FrameworkEvent.ERROR. If the Framework implements the optional Start Level specification, this behavior is different. See Start Level Service Specification on page 203. During the shutdown, bundles with a lazy policy
must not be activated even when classes are loaded from them.
3. Event handling is disabled.
框架有時(shí)也需要被關(guān)閉,這通常由關(guān)閉系統(tǒng)bundle引起,當(dāng)框架關(guān)閉時(shí),必須發(fā)生以下行為:
1. 系統(tǒng)bundle進(jìn)入STOPPING狀態(tài)
2. 所有ACTIVE狀態(tài)的bundles通過Bundle.stop方法停止,除非他們的被持久保存的狀態(tài)指示當(dāng)框架下次啟動(dòng)后沒有改變時(shí)它們必須被重啟。 在這期間發(fā)生的任何exceptions必須被包裝成一個(gè)BundleException,并發(fā)布為一個(gè)類型為FrameworkEvent.ERROR 的框架事件。框架關(guān)閉期間,帶有一個(gè)lazy激活策略的bundle必須不能被激活,即使他們的類被加載。
3. 事件處理被禁用
4.8 Security
4.8.1 Admin Permission
The Admin Permission is a permission used to grant the right to manage the Framework with the option to restrict this right to a subset of bundles, called targets. For example, an Operator can give a bundle the right to only manage bundles of a signer that has a subject name of ACME:Admin Permission是一個(gè)權(quán)限,用于授予管理框架的權(quán)力,附帶用于將這個(gè)權(quán)力約束到bundles的子集的選項(xiàng),也可稱為targets。例如,一個(gè)操作人員可以給予一個(gè)bundle這樣的權(quán)利:管理有一個(gè)主題名為ACME的簽名者的bundles:
org.osgi.framework.AdminPermission("(signer=\*, o=ACME, c=us)",
)

The actions of the Admin Permission are fine-grained. They allow the deployer to assign only the permissions that are necessary for a bundle. For example, an HTTP implementation could be granted access to all resources of all bundles.
Admin Permission的行為是細(xì)粒度的,這些行為允許開發(fā)者僅僅分派一個(gè)bundle必要的的權(quán)限。例如,一個(gè)HTTP實(shí)現(xiàn)可以被授予訪問所有bundle的所有資源的權(quán)限。
org.osgi.framework.AdminPermission("*", "resource" )
Code that needs to check Admin Permission must always use the constructor that takes a bundle as parameter: AdminPermission(Bundle,String) with a single action. This is to ensure the fastest execution of the permission check.
需要檢查Admin Permission的代碼必須總是使用一個(gè)以一個(gè)bundle和一個(gè)行為 做為參數(shù)的構(gòu)造器:AdminPermission(Bundle,String),這是為了確保最快的執(zhí)行權(quán)限檢查。
For example, the implementation of the loadClass method must check that the caller has access to the class space:
例如,方法loadClass方法的實(shí)現(xiàn)必須檢查調(diào)用者(也就是當(dāng)前bundle)具有訪問這個(gè)類空間的權(quán)限:
public class BundleImpl implements Bundle {
Class loadClass(String name) {
securityManager.checkPermission(new AdminPermission(this,"class") );

}
}
Class loadClass(String name) {
securityManager.checkPermission(new AdminPermission(this,"class") );

}
}
When assigning permissions to the bundle via (Conditional) Permission Admin service, it is difficult for the administrator to have a priori knowledge of the bundle ID assigned to a bundle. In order to provide a more flexible way to designate the bundle for an Admin Permission, (Conditional)Permission Admin must provide special support for creating AdminPermission objects from a PermissionInfo object. When a Permission Info specifies an Admin Permission, the name parameter of the Permission Info must be a filter string. This filter has the same syntax as an OSGi filter but has special rules for wildcards in the location and signer attributes.
當(dāng)通過Permission Admin service分派權(quán)限到bundle時(shí),很難事管理員具有對bundle ID的先驗(yàn)知識(shí)(注:這里的先驗(yàn)知識(shí)是指推理bundle ID的分派情況,參見 http://www.importanceofphilosophy.com/Irrational_APriori.html)。 為了提供一個(gè)更靈活的方法給一個(gè)Admin Permission指派bundle,Permission Admin必須給AdminPermission對象的生成提供特殊的來自PermissionInfo對象的支持。當(dāng)一個(gè)Permission Info指定了一個(gè)Admin Permission,Permission Info的name參數(shù)必須是一個(gè)過濾器字符串,這個(gè)過濾器與OSGi過濾器具有相同的語法,只是路徑和簽名者屬性中的通配符具有特殊的規(guī)則。
The filter can contain the following keys:
• id – The bundle ID of the designated bundle. For example: (id=256)
• location – The location of a bundle. Filter wildcards for Strings are supported, allowing the value to specify a set of bundles. For example:
(location=https://www.acme.com/download/*)
• signer – A Distinguished Name chain. See the Certificate Matching on page 21 for more information how Distinguished Names are matched. Wildcards in a DN are not matched according to the filter string rules, but according to the rules defined for a DN chain. The wildcard character (’*’ or \u002a) must be escaped with a backslash (’\’) to avoid being interpreted
as a filter wildcard. For example:
(signer=\*,o=ACME,c=NL)
• name – The symbolic name of a bundle. Filter wildcards for Strings are supported allowing the value to specify a set of bundles. A single symbolic name may also map to a set of bundles. For example:
(name=com.acme.*)
The complete filter can also be a single wildcard character (’*’ or \u002a). In that case all bundles must match.
4.8.1.1 Actions
The action parameter of Admin Permission will specify the subset of privileged administrative operations that are allowed by the Framework. The actions that are architected are listed in table Table 4.8. Future versions of the specification, as well as additional system services, can add additional actions. The given set should therefore not be assumed to be a closed set.
The special action "*" will represent all actions.
Each bundle must be given AdminPermission(<bundle identifier>, "resource,metadata,class") so that it can access its own resources. This is an implicit permission that must be automatically given to all bundles by the Framework.
The actions resolve and startlevel must use the system bundle as target.
The implementation of the AdminPermission class requires close integration with the Framework implementation. However, an AdminPermission class accompanies the specification. Framework implementations can change this class if they so desire. However, the default implementation provided must load a Framework implementation provided class when it is loaded. This class comes from the package named in the following property:
org.osgi.vendor.framework
The class named AdminPermission in that package must be used to instantiate a new Permission object using the constructor with the same signature to which all the AdminPermission methods must delegate.
4.8.2 Using Signer for the Target
The Admin Permission use the signer of the bundle to select a target. For example, a bundle could be granted the permission to perform life cycle operations on bundles signed by a particular principal.Using the principal (signer) as target, the maintenance of the permission management can be significantly reduced because it is not necessary to configure for individual bundles: the signer is effectively used as a grouping mechanism. However, one must consider that signatures can be added by any part, thereby causing it to become eligible for management by bundles
that have the permission to administrate specific signers.
Using multiple signers is both a feature as well as it is a possible threat. From a management perspective it is beneficial to be able to use signatures to handle the grouping. However, it can also be used to maliciously manage a trusted bundle.
For example a trusted bundle signed by T, could later have a signature added by an untrusted party U. This will grant the bundle the permissions of both T and U, which ordinarily is a desirable feature. However, If the permissions associated with signer U also allow the management of bundles signed by U, then U could unexpectedly gain the permission to manage this trusted bundle.For example, it could now start and stop this trusted bundle. This unexpected effect of becoming eligible to be managed should be carefully considered when multiple signers are used.
4.8.3 Privileged Callbacks
The following interfaces define bundle callbacks that are invoked by the Framework:• BundleActivator
• ServiceFactory
• Bundle-, Service-, and FrameworkListener.
When any of these callbacks are invoked by the Framework, the bundle that caused the callback may still be on the stack. For example, when one bundle installs and then starts another bundle, the installer bundle may be on the stack when the BundleActivator.start method of the installed bundle is called. Likewise, when a bundle registers a service object, it may be on the stack when the Framework calls back the serviceChanged method of all qualifying ServiceListener objects.
Whenever any of these bundle callbacks try to access a protected resource or operation, the access control mechanism should consider not only the permissions of the bundle receiving the callback, but also those of the Framework and any other bundles on the stack. This means that in these callbacks, bundle programmers normally would use doPrivileged calls around any methods protected by a permission check (such as getting or registering service objects).
In order to reduce the number of doPrivileged calls by bundle programmers, the Framework must perform a doPrivileged call around any bundle callbacks. The Framework should have java.security.AllPermission. Therefore, a bundle programmer can assume that the bundle is not further restricted except for its own permissions.
Bundle programmers do not need to use doPrivileged calls in their implementations of any callbacks registered with and invoked by the Framework.
For any other callbacks that are registered with a service object and therefore get invoked by the service-providing bundle directly, doPrivileged calls must be used in the callback implementation if the bundle’s own privileges are to be exercised. Otherwise, the callback must fail if the bundle that initiated the callback lacks the required permissions.
A framework must never load classes in a doPrivileged region, but must instead use the current stack. This means that static initializers and constructors must not assume that they are privileged. Any privileged code in a static initializer must be guarded with a doPrivileged region in the static initializer. Likewise, a framework must not instantiate a BundleActivator
object in a doPrivileged region, but must instead use the current stack. This means that the BundleActivator constructor must not assume that it is privileged.
4.8.4 Lazy Activation
The activation policy, see Activation Policies on page 85, can indirectly cause the activation of a bundle. AdminPermission[*,CLASS ] therefore implies the EXECUTE action during a loadClass method call. Normal class loading caused by executing Java class code must not requireAdminPermission[*,EXECUTE ].
4.9 Changes 4.1
• Expressly indicated that Fragment bundles can not be started and must not have a Bundle Activator.• Added a LAZY_ACTIVATION event.
• Added a getBundleContext method to the Bundle interface in Access to a Bundle’s Bundle Context on page 92. Added a section for the required Admin Permission
• Added activation policies, see Activation Policies on page 85.
• Add properties for Windows Vista and 64 bit processors. See Environment Properties on page 93.
• Added a new start and stop method that take an int to specify the start/ stop option.
• An option is defined to start bundles transient, that is, starting the bundle but not changing the recorded start state.
• Added text to ensure that events are delivered in order.
posted on 2008-05-09 17:57 gembin 閱讀(1238) 評(píng)論(0) 編輯 收藏 所屬分類: OSGi