gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          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.
          生命周期層提供了一個用于控制bundle的安全和生命周期操作的API,這個層是基于模塊層和安全層的。

          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 – 生命周期層必須實現一個全面涵蓋bundle的安裝,啟動,停止,更新,卸載和監控的API。
          • Reflective –這個API必須提供對框架的實際狀態的完整監察。
          • Secure – 必須能夠在一個細粒度權限的安全環境中使用API,但是安全必須是可選的。
          • Manageable – 必須可以遠程管理一個服務平臺。

          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.
          一個bundle是一個在OSGi框架中被執行的JAR文件。類加載方面的概念定義在模塊層中,但是模塊層沒有定義一個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).
          一個bundle的安裝只能被執行于另一個bundle或通過實現來執行。

          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.
          一個bundle通過它的Bundle Activator來啟動。它的Bundle Activator由頭Bundle-Activator指定。這個指定的類必須實現BundleActivator 接口。這個接口有一個start方法和stop方法,給bundle開發人員注冊它自己的監聽器和啟動一些必要的線程。stop方法必須清除和停止所有由 它啟動的線程。

          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的時候,它會收到一個Bundle Context。這個Bundle Context接口的方法可以粗略地分成以下類別:
          • Information – 訪問關于余下的框架信息(可理解為框架中其他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服務平臺中的每一個bundle,都有一個關聯的Bundle對象。這個對象可以用來管理bundle的生命周期。這通常是由一個Management Agent來完成,它也是個bundle。

          4.3.1 Bundle Identifiers

          A bundle is identified by a number of names that vary in their scope:
          一個bundle通過以下幾點來識別:

          • 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 – 一個長整型,是框架為一個bundle的整個生命周期所指派的唯一標識符,即使這個bundle被更新或框架重啟。目的就是在框架中區別出 bundles。當bundle安裝的時候,bundle標識符是根據升序來進行指派的,方法getBundleId()返回bundle的標識符。
          • Bundle location – 在安裝bundle的時候,由management agent指派給一個bundle的名字。這個字符串可以被理解為一個JAR文件的URL,但是不是強制的。這個URL在框架中必須是唯一的。在 bundle被更新的時候,這個URL必須不能被改變,它是一個bundle的具有唯一性的標識符。
          • Bundle Symbolic Name – 由開發人員指派的名字。bundle版本和bundle標記名結合是一個bundle的全局唯一標識符。

          4.3.2 Bundle State

          A bundle can be in one of the following states:
          一個bundle可以是以下其中一個狀態:

          • 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已經被成功安裝。
          • RESOLVED – bundle所需要的所有類都可用。這個狀態表示,這個bundle已經準備好被啟動或是被停止了。
          • STARTING – bundle正在被啟動,方法BundleActivator.start將被調用,但是還沒有return。如果bundle含有activation policy,那么bundle將一直處于STARTING,直到根據它的activation policy來激活它。
          • ACTIVE – bundle被成功激活并運行;它的BundleActivator.start方法被調用并return了。
          • STOPPING – bundle正在被停職。BundleActivator.stop方法已經被調用,但是還沒有return。
          • UNINSTALLED – 卸載,它不能進入其他狀態。




          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.
          當一個bundle被安裝后,它將被一直保存在框架的持久存儲中,知道它被卸載。不管一個bundle是被啟動還是停止,都必須記錄在框架的持久存儲中。 一個bundle被永久地保存為啟動,那么它必須在框架啟動時就被啟動,除非它被明確停止。啟動級別服務會影響bundle的實際啟動和停止。

          The Bundle interface defines a getState() method for returning a bundle’s state.
          Bundle接口定義了一個getState()方法來獲取bundle的狀態。

          If this specification uses the term active to describe a state, then this includes the STARTING and STOPPING states.
          如果規范使用術語active(激活)來描述一個狀態,那么它表示STARTING或STOPPING狀態。

          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狀態可以被表示成一個bit-mask,盡管任何時候一個bundle只能處于一種狀態。下面的代碼示例可以用于決定bundle是否處于STARTING,ACTIVE或STOPPING狀態
          if ((b.getState() & (STARTING | ACTIVE | STOPPING) != 0)
            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,傳遞給一個bundle的Bundle Activator,定義一下方法用于安裝一個bundle
          • installBundle(String) – 從指定的路徑(URL)安裝一個bundle
          • installBundle(String,InputStream) – 從指定的InputStream 對象安裝一個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.
          一個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.
          每一個bundle都由它的路徑字符串唯一識別,如果一個已經安裝的bundle使用的是指定的路徑,installBundle 方法必須返回這個已經安裝了的bundle對象,而不是安裝一個新bundle。

          The Framework must assign a unique bundle identifier that is higher than any previous bundle identifier.
          框架必須指派一個唯一bundle標識符(long型),這個標識符應該大于先前安裝的任何bundle的標識符。

          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.
          框架中一個bundle的安裝必須是:
          • Persistent – 這個bundle必須保持安裝于框架和JAVA VM調用器知道它被明確卸載。
          • Atomic – 必須完全安裝一個bundle,如果安裝失敗,OSGi服務平臺必須返回到安裝前的狀態。

          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.
          一旦一個bundle被安裝,Bundle對象就被生成了,所有生命周期的操作必須執行在這個對象之上。返回的Bundle對象可以start,stop,update和uninstall這個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.
          當框架成功解析一個bundle的manifest中表述的依賴關系后,這個bundle可以進入RESOLVED狀態。

          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.
          一個bundle可以通過調用start方法來啟動,或是框架能自動啟動這個bundle,如果它已經準備好,bundle的自動啟動設置表示它必須被啟動。

          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.
          如果滿足以下條件,一個bundle就準備好可以啟動了:
          • bundle可以被解析
          • 如果可選啟動級別服務被啟用,那么bundle必須滿足這個啟動級別

          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.
          一旦一個bundle被啟動,它必須被激活,通過將控制權給它,以便它能初始化。這個激活可以立刻發生,或加載第一個來自這個bundle的的類時 (lazy activation,懶激活)。重啟或修改啟動級別之后,一個啟動了的bundle可能需要由框架再次自動將其啟動。

          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.
          因此框架必須為每一個bundle維護一個持久的自動啟動設置,這個啟動設置可以有以下值:
          • Stopped –bundle不應該被啟動。
          • Started with eager activation – 一旦bundle準備好,它必須被啟動,優先激活
          • Started with declared activation –一旦bundle準備好,它必須被啟動,必須根據它的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)來啟動一個bundle并控制自動啟動設置。這個方法有一個整型參數,為其定義了以下值:
          • 0 – 優先激活的啟動bundle,將自動啟動設置 設置為Started with declared activation。如果這個bundle已經被設置為lazy activation policy啟動,正在等待激活,那么它必須被馬上激活。
          • START_TRANSIENT – 與0一樣,但是自動啟動設置必須不能被修改,如果bundle不能被啟動,例如,bundle沒有準備好,那么一個BundleException必須被拋出。
          • START_ACTIVATION_POLICY – 使用聲明在manifest中頭Bundle-ActivationPolicy里的激活策略來啟動bundle,并將自動啟動設置 設置為Started with declared activation
          • START_ACTIVATION_POLICY | START_TRANSIENT – 使用聲明的激活策略啟動bundle,但不改變自動啟動設置。

          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.
          當啟動bundle的時候,框架必須嘗試解析這個bundle,如果它還沒有被解析。如果解析失敗,start方法必須拋出一個BundleException。在這個情況下,bundle的自動啟動設置必須始終被設置,除非使用的是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.
          當start方法return的時候,沒有exception,那么這個bundle的狀態將會是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.
          可選的啟動級別服務影響了bundles的實際啟動和停止的順序。它也能用來查詢自動啟動設置:
          • isBundlePersistentlyStarted(Bundle) – 如果bundle的自動啟動設置為Stopped,該值為false,否則為true。
          • isBundleActivationPolicyUsed(Bundle) – 如果bundle的自動啟動設置表示manifest中聲明的激活策略必須被使用,該值為true,如果bundle必須優先激活,值為false。
          片段bundles不能被啟動,如果嘗試啟動它們必須引起一個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:
          一個bundle通過調用它的Bundle Activator對象來激活,如果這個對象存在。接口BundleActivator定義了一些方法,當bundle啟動時或停止由框架調用它們。
          為了通知做為全屬性類名的OSGi環境的服務的Bundle Activator,bundle開發者必須聲明頭Bundle-Activator,框架必須實例化一個這個類的對象,并將其cast為一個 BundleActivator的實例。然后它必須調用BundleActivator.start方法來啟動這個bundle。
          下面是一個頭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.
          一個扮演了Bundle Activator的類必須實現接口BundleActivator,聲明為public,有一個public的默認構造函數,可以通過Class.newInstance來創建一個它的實例。

          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.
          提供一個Bundle Activator是可選的,例如,一個類庫bundle僅僅輸出一些包,不需要定義Bundle Activator。另外,還有一些其他機制用于獲取控制權和獲得一個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 定義了以下方法,用于啟動和停止一個bundle:
          • start(BundleContext) – 這個方法能夠分派bundle需要的資源,啟動線程,注冊服務等。如果這個方法不注冊任何方法,可以在后面當它需要的時候再注冊:例如,在一個回調或一個 外部事件中,只要是它處于ACTIVE狀態,都可以注冊服務。如果這個方法拋出一個exception,框架必須標記這個bundle為stopped, 然后發出STOPPING和STOPPED事件,但是必須不能調用Bundle Activator的stop(BundleContext)方法
          • stop(BundleContext) – 這個方法必須撤銷BundleActivator.start(BundleContext)方法中的所有行為,但是沒有必要注銷服務和框架的監聽器,因為它們是由框架來清理的。

          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.
          當一個bundle啟動的時候,一個Bundle Activator必須被創建,也意味著一個class loader的生成。對于一個大的系統,這種策略會明顯的增加啟動時間,增加一些不必要的內存開銷。Service Component Runtime和激活策略能緩解這個問題。

          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:
          一個bundle的激活也可以使用一個激活策略,晚于它的啟動時間。這個策略指定在頭Bundle-ActivationPolicy中:
          Bundle-ActivationPolicy ::= policy ( ’;’ directive )*
          policy ::= ’lazy’

          The only policy defined is the lazy activation policy. If no Bundle-ActivationPolicy header is specified, the bundle will use eager activation.
          這里僅定義了一個lazy激活策略。如果頭Bundle-ActivationPolicy沒有被指定,bundle將使用優先激活。

          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.
          一個lazy激活策略表示這個bundle一旦啟動,必須不能被激活,直到它其中的一個類被加載,在普通的類加載期間或通過Bundle的 loadClass方法加載。資源的加載不會觸發bundle的激活。這個從默認的優先激活策略而來的改變被反射在bundle狀態和它的時間中。當一個 bundle使用lazy激活策略啟動時,必須通過以下步驟:
          • 這個bundle的BundleContext被創建。
          • bundle的狀態變為STARTING。
          • LAZY_ACTIVATION事件被觸發。
          • 系統等待這個bundle的類加載的出現(當加載它的類的時候,它才被激活)。
          • 事件STARTING被觸發。
          • bundle被激活。
          • bundle的狀態變為ACTIVE。
          • STARTED事件被觸發。

          如果Bundle Activator方法拋出一個exception導致激活失敗,bundle必須被停止,但是不調用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激活策略允許一個框架實現延遲bundle的class loader的生成和bundle的激活,直到這個bundle第一次被使用,通常是在啟動時,保存資源和初始化的時候發生。
          默認情況下,加載一個類會觸發lazy激活,但是加載資源必須不能觸發激活。lazy激活策略能定義以下會引發激活的的類:
          • include – 包名列表,當這個列表中的任何一個包中的類被加載,必須觸發激活。默認是bundle中所有的包都會觸發。
          • exclude – 包名列表,當這個列表中的任何一個包中的類被加載,必須不能觸發激活。默認是沒有包。
          例如:
          Bundle-ActivationPolicy: lazy;
          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.
          當一個類加載觸發lazy激活時,框架必須首先定義這個觸發類,這個定義能觸發其他的lazy激活。這些激活必須被延遲,知道所有涉及的類加載和定義都完 成,然后,激活必須根據觸發的倒序來執行。也就是說,最后被檢測到的激活必須首先被執行。所有被延遲的激活完成之后,觸發激活的類加載才返回加載的類的對 象。如果在這個過程中出現任何錯誤,將被報告為一個Framework ERROR事件。但是類加載必須正常完成。一個lazy激活失敗的bundle不應該再次被激活,除非框架重啟,或這個bundle通過調用Bundle start方法被明確啟動。

          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接口為停止一個bundle定義了方法stop(int)。
          它將停止一個bundle,并把bundle的狀態設置為RESOLVED,它有個整型參數,可以有以下值:
          • 0 – 如果這個bundle處于激活狀態,那么解除激活,設置自動啟動設置為Stopped。
          • STOP_TRANSIENT – 如果bundle處于激活狀態,那么解除激活。但是不改變它的自動啟動設置。

          The stop() method calls stop(0).
          調用stop()相當于調用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.
          嘗試停止一個片段bundle必須引發一個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 code
          may 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接口定義了一個stop(BundleContext)方法,它由框架調用來停止一個bundle。這個方法必須釋放所有 激活時分派的所有資源。關聯到這個即將停止的bundle的所有線程應該被立即停止。一旦stop方法返回,線程代碼將不再能使用框架相關的對象(例如 services 和BundleContext )。
          如果這個即將停止的bundle注冊了任何服務,那么框架必須自動注銷這些服務。因此,沒有必要在stop方法中注銷任何服務。

          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.
          框架必須保證,如果一個BundleActivator.start方法執行成功,那么當這個bundle被解除激活的時候,必須調用同一個 BundleActivator對象的BundleActivator.stop方法,stop方法調用之后,這個BundleActivator對象將 不會再使用到。
          一個停止了的bundle輸出的包對其他bundle繼續有效,這里的繼續輸出暗指其他bundle可以執行一個停止了的bundle的代碼,一個bundle的設計者應該確保這不會造成危害。通常為了確保他們不能被執行,接口應該不包含可執行代碼。

          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個方法用于更新一個bundle:
          • update() – 更新一個bundle
          • update(InputStream) – 從指定的InputStream對象更新一個bundle

          更新過程支持從一個bundle的當前版本移植到一個新版本。一個更新的bundle的輸出必須立即對框架有效,如果舊版本的輸出沒有被用到,那么輸出將 被移除,否則,所有舊版本的輸出都保持有效。直到PackageAdmin.refreshPackages方法被調用,或是框架重啟。

          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 the
          bundle from the persistent storage of the Framework.
          接口Bundle定義了uninstall()方法用于從框架中卸載一個bundle。這個方法會引起框架通知其他bundles,這個bundle正在 被卸載,并設置這個bundle的狀態為UNINSTALLED。不論這個bundle關聯到哪,框架必須刪除與這個bundle相關的所有資源。這個方 法從框架的持久存儲中卸載這個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.
          一旦這個方法返回,OSGi服務平臺的狀態必須與從未安裝這個bundle的狀態一致,除非:
          • 這個被卸載的bundle輸出的有包(通過頭Export-Package)。
          • 這個被卸載的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.
          如果輸出沒有被使用,那么它們必須被移除,否則如果有輸出被使用,那么所有的輸出必須對其他已經存在的bundle和將要解析的bundle可用,直到refreshPackages方法被調用,或框架重啟。

          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對象提供了一個方便的方法去檢測一個bundle的改變。
          框架必須保持一個bundle被其生命周期操作所做的改變的次數,方法getLastModified()將返回這個bundle被安裝,更新或卸載后所做的最后一次改變。最后修改時間必須被持久保存。

          這個方法必須返回從Jan. 1, 1970 UTC晚上12點到現在的毫秒數,這個毫秒數的每次改變都要大于上一次修改的時間。

          當一個bundle緩存其他bundle的資源時,當它改變時需要刷新緩存,方法getLastModified()將非常有用。目標bundle的生命周期變化可以在緩存bundle不活躍時發生,因此最后修改時間可以方便的跟蹤這些目標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個方法用于返回manifest頭信息:getHeaders()和 getHeaders(String)。
          • getHeaders() – 返回一個Dictionary對象,包含了bundle的manifest頭的鍵/值對。返回的值根據java.util.Locale.getDefault返回的默認locale來進行本地化。
          • getHeaders(String) – 返回一個Dictionary 對象,包含了bundle的manifest頭的鍵/值對。返回的值使用指定的locale來進行本地化,這個locale可以是以下值:
            • null – 由java.util.Locale.getDefault返回的默認locale,將使這個方法與getHeaders()方法一樣。
            • Empty string – dictionary將包含未本地化的行,manifest頭,包括'%'(參見本地化那節)
            • 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.

          如果一個指定的key沒有譯文,Bundle.getHeaders返回的Dictionary對象將返回指定在manifest中的值,不包含'%'。
          這2個方法需要AdminPermission[<bundle>, METADATA],因為有些頭信息是很敏感的,例如Export-Package中的包列表,Bundle對象總是有讀取他們自己的頭的權限。
          bundle進入UNINSTALLED狀態后,getHeaders方法必須繼續提供頭信息。bundle被卸載之后,這個方法僅僅返回頭的原始數據或默認locale的本地化值。一個框架實現在處理頭的時候必須只能使用原始頭,本地化必須不能影響框架的操作。

          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內部加載類一樣的加載某些類,loadClass(String)方法可以訪問bundle的class loader。它可以用來:
          • 加載另外一個bundle的插件
          • 啟動一個應用程序模型的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.
          例如,一個應用程序模型可以使用這個特性去加載一個bundle的初始化類,并根據這個模型的規則啟動它。
          void appStart() {
            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.
          加載一個bundle的類會激活這個bundle,如果這個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:
          一個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)方法提供了對資源的訪問,這個資源與52頁中Overall Search Order描述的類空間資源是一致的。按照這個查找順序可能會使JAR文件的某些部分不可訪問。這2個方法需要bundle被解析,如果bundle沒有 被解析,框架必須嘗試解析它。
          這個查找順序能隱藏JAR文件的某些目錄,split包需要被考慮進去,因此,具有相同包名的資源可以來自不同的JAR文件。如果bundle沒有被解析 (或不能被解析),getResource 和getResources 方法必須只能從bundle的類路徑中加載資源。這個查找策略應該被用于訪問自己的資源的代碼。調用其中一個方法能引起一個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個方法的目的是提供低級別的訪問,不需要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)方法是一個媒介形態,當需要其他bundle的配置或設置信息時會很有用,這個 bundle可以被認為是片段bundle,但是必須不能創建一個class loader,這個方法提供了對象關聯的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接口定義了一個方法,用于返回適合一個bundle的權限的信息:hasPermission(Object)。如果bundle的保護域有 指定的權限,該方法返回true,否則返回false,或者如果參數指定的object不是java.security.Permission的實例,也 返回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].

          被啟動的bundles都會有一個BundleContext,這個對象是一個只能被bundle使用的功能對象。但是有很多情況下,bundles必須 扮演成另外的bundles,例如,Service Component Runtime注冊服務就扮演著其他bundle。因此框架必須通過getBundleContext()方法提供對別的bundle的context的 訪問。如果一個bundle沒有BundleContext,必須是因為它是一個片段bundle或它的狀態不是 STARTING,ACTIVE,STOPING,這時這個方法必須返回null。
          這個方法有一定的潛在危險,因為它允許bundle扮演成其他任何bundle。在一個安全系統,需要AdminPermission[*,CONTEXT]來保護這個方法。


          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之間的聯系是通過使用BundleContext對象來搭建的,一個BundleContext對象是平臺中的一個bundle的執行上下文,它扮演底層框架的代理。

          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.

          一個BundleContext是當bundle啟動的時候由框架生成的。這個bundle可以使用它的私有的BundleContext 對象實現以下功能:
          • 安裝新bundle。
          • 查詢其他已經安裝的bundles
          • 獲得一個持久存儲區域(參見JavaDoc: getDataFile(java.lang.String filename) )
          • 獲取一個注冊了的服務
          • 注冊一個服務到框架服務中
          • 訂閱或退訂框架的時間廣播。


          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.

          當一個bundle啟動時,框架生成一個BundleContext對象,并將它作為參數提供給bundle的BundleActivator的 start(BundleContext)方法。每個bundle都有它自己的BundleContext對象,這些對象不能在bundles間相互傳 遞,因為這個BundleContext對象關系到一個bundle的安全方面和資源分配。

          stop(BundleContext)方法返回后,BundleContext對象必須不再能使用。如果使用一個停止了的bundle的BundleContext,框架必須拋出一個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定義了一些方法,用于獲取安裝在平臺中的bundles的信息:
          • getBundle() – 返回與當前BundleContext相關聯的Bundle對象。
          • getBundles() – 返回當前安裝在框架中的bundles集合
          • getBundle(long) – 返回具有指定的唯一標識符的bundle對象,如果沒有找到匹配的bundle,返回null
          bundle的訪問是不受限制的,任何bundle都可以列舉已經安裝了的bundles的集合,和可以識別bundle的信息,例如它的路徑,它的頭信息,但是訪問者必須要有AdminPermission[<bundle>,METADATA]權限。

          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.
          框架應該為每一個已經安裝了的bundle提供一個私有的持久存儲區域,這個區域是操作系統支持的文件結構。

          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 接口根據類File定義對這個存儲區域的訪問,它支持具有平臺依賴的文件名和目錄名。

          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 定義了一個方法用于訪問私有持久存儲區域:getDataFile(String),文件名作為參數,它將這個文件名轉換成bundle的持久存儲區域中 的絕對路徑文件名,然后返回這個File對象,如果沒有持久存儲支持,將返回null。框架必須自動給bundle提供 FilePermission[<storage area>, READ | WRITE | DELETE]權限,以便這個bundle能讀,寫,刪除存儲區域中的文件。


          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.

          如果需要執行權限,那么一個相對路徑名字可以被用于文件權限定義,例如,FilePermission[bin/*, EXECUTE]指定bundle的私有數據區域的子目錄可能包含可執行文件。這僅僅只提供java環境中的執行權限,不會處理執行文件潛在的操作系統問 題。
          這個特殊的處理僅僅用于分派給一個bundle的文件權限對象,默認的權限不受影響,一個通過setDefaultPermission指派的相對路徑名字的文件權限必須不能被忽略。

          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定義了一個用于返回屬于框架屬性信息的方法:properties: getProperty(String),這個方法能夠返回以下屬性信息:
          所有的框架屬性可能由操作人員定義為系統屬性,如果這些屬性沒有定義為系統屬性,框架必須從相關的標準JAVA系統屬性構造這些屬性。

          屬性列表略.....

          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,框架本身也可以看成是一個bundle,框架bundle被引用為系統bundle。通過系統bundle,框架可以注冊服務供其他bundle使用,例如 Package Admin和Permission Admin services。
          系統bundle被列在由BundleContext.getBundles()返回的安裝bundles集合中,盡管它與其他bundles有以下區別:

          • The system bundle is always assigned a bundle identifier of zero (0).
          • 系統bundle的標識符(ID)總是被分派為0.
          • The system bundle getLocation method returns the string: "System Bundle", as defined in the Constants interface.
          • 系統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.
          • 系統bundle的每一個版本都有一個唯一的bundle標記名,但是,system.bundle必須被公認為這個由框架定義的bundle名字的別名。
          • The system bundle’s life cycle cannot be managed like normal bundles. Its life cycle methods must behave as follows:
          • 系統bundle的生命周期不能像普通bundle那樣管理,它的生命周期方法必須表現為以下幾點:
            • 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.

          框架生命周期層支持一下時間類型:
          • BundleEvent – 報告bundles的生命周期的變化
          • FrameworkEvent – 報告框架啟動,啟動級別被修改,包被刷新,或是遇到的錯誤。
          被報告的具體事件可以使用getType方法來獲取,這個方法返回的整數是類中描述的恒量名字中的一個。但是,事件可以(在以后的版本中將)被擴展,自定義事件類型應該被忽略。

          4.6.1 Listeners

          A listener interface is associated with each type of event. The following list describes these listeners.
          一個監聽器接口關聯著事件的每個類型。以下列表描述了這些監聽器
          • 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:
          當一個bundle的生命周期信息被改變的時候被調用,并伴隨一個類型為BundleEvent的事件。 SynchronousBundleListener對象在處理事件期間被同步調用,必須在任何BundleListener對象調用之前調用它,以下事 件將在bundle的狀態發生改變時由框架發送出去:

            • 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被指定了一個lazy激活策略;它的激活將被延遲到后面的時間點上,狀態被設置為STARTING,因為LAZY_ACTIVATION不可 以被發送到監聽器,只能被發送到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接口定義了可以用來添加和刪除監聽器的每個類型的方法。

          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).

          事件可以被同步發送,除非特殊說明,也就是說事件不一定要在生成他們的線程中發送,但是沒有定義用于調用一個事件監聽器的線程。
          如果一個回調事件監聽器生產生了一個未檢查的exception,框架必須發布一個FrameworkEvent.ERROR - 除非回調時當時正在發布一個FrameworkEvent.ERROR(為了防止一個無限循環[問:這里的無限循環從何而來?])。

          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.

          如果框架同步發送事件,它必須:
          • 在事件發布前收集一個監聽器列表的快照(而不是優先發布事件),但是這是在事件發布之前,所以事件發生后(事件發布前),監聽器并沒有進入這個列表。
          • 確保在快照收集好后,列表中的監聽器在事件發布時仍然屬于激活的bundles。
          • 可以使用多個線程發布事件,如果是這樣,各個handler接收事件的順序必須與事件被提交的順序一致,這確保了handlers能根據它希望的順序來接收事件。

          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.
          當事件發布時,如果框架沒有捕獲當前監聽器列表,而是等待事件發布,應該出現以下錯誤:一個bundle被啟動并注冊了一個監聽器,那么這個bundle可以看見它自己的BundleEvent.INSTALLED事件。

          The following three scenarios illustrate this concept.

          1. Scenario one event sequence:
          • Event A is published. 事件A被發布
          • Listener 1 is registered. 監聽器1被注冊
          • Asynchronous delivery of Event A is attempted. 嘗試同步發布事件A。
          Expected Behavior: Listener 1 must not receive Event A, because it was not registered at the time the event was published.監聽器1必須不能收到事件A。

          2. Scenario two event sequence:
          • Listener 2 is registered. 監聽器2被注冊
          • Event B is published. 事件B被發布
          • Listener 2 is unregistered.監聽器2被注銷
          • Asynchronous delivery of Event B is attempted. 嘗試同步發布事件B。
          Expected Behavior: Listener 2 receives Event B, because Listener 2 was registered at the time Event B was published.監聽器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.
          通常,調用一個監聽器的bundle不應該持有任何Java監視器,意思是說,當回調發生時,框架和同步事件創造者都不應該在一個監視器中。

          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.
          一個Java監視器的目的是為了保護數據結構的更新,這應該是一個很小的代碼區域,不調用任何不能具備監視效果的代碼。從同步代碼調用OSGi框架會引起意想不到的負面效果,其中一個負面效果可能是死鎖。

          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(超時)能用來打破死鎖,但是Java監視器沒有time-outs,因此,這些代碼將被永久懸掛直到系統重啟(Java已經deprecated所有能停止一個線程的方法),防止這種死鎖只能是不要再一個同步塊中調用框架。

          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.
          一個框架實現,必須在提供任何服務之前被啟動,一個框架如何由一個操作員啟動并沒有定義在這個規范中,因為它會因為實現的不同而不同。一些框架實現可能提供命令行選項,其它的可能會通過一個配置文件讀取啟動信息,總的來說,框架實現必須以相應的順序執行以下所有的動作

          4.7.1 Startup

          When the Framework is started, the following actions must occur:
          當框架啟動時,必須出現以下動作:
          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. 事件處理被啟用,現在事件可以被傳達給監聽器
          2. 系統bundle進入STARTING狀態。
          3. 所有被記錄為started的以前安裝了的bundle必須根據Bundle.start來啟動,啟動時,任何exceptions必須被包裝為一個 BundleException并發布為一個框架事件,類型為FrameworkEvent.ERROR。如果框架實現了可選的啟動級別規范,這個行為將 有所區別,任何指定了激活策略的bundle必須根據它們的激活策略來對待。
          4. 系統bundle進入ACTIVE狀態
          5. 一個類型為FrameworkEvent.STARTED的框架時間被發布出去。

          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.

          框架有時也需要被關閉,這通常由關閉系統bundle引起,當框架關閉時,必須發生以下行為:
          1. 系統bundle進入STOPPING狀態
          2. 所有ACTIVE狀態的bundles通過Bundle.stop方法停止,除非他們的被持久保存的狀態指示當框架下次啟動后沒有改變時它們必須被重啟。 在這期間發生的任何exceptions必須被包裝成一個BundleException,并發布為一個類型為FrameworkEvent.ERROR 的框架事件。框架關閉期間,帶有一個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是一個權限,用于授予管理框架的權力,附帶用于將這個權力約束到bundles的子集的選項,也可稱為targets。例如,一個操作人員可以給予一個bundle這樣的權利:管理有一個主題名為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的行為是細粒度的,這些行為允許開發者僅僅分派一個bundle必要的的權限。例如,一個HTTP實現可以被授予訪問所有bundle的所有資源的權限。
          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的代碼必須總是使用一個以一個bundle和一個行為 做為參數的構造器:AdminPermission(Bundle,String),這是為了確保最快的執行權限檢查。

          For example, the implementation of the loadClass method must check that the caller has access to the class space:
          例如,方法loadClass方法的實現必須檢查調用者(也就是當前bundle)具有訪問這個類空間的權限:
          public class BundleImpl implements Bundle {
            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.
          當通過Permission Admin service分派權限到bundle時,很難事管理員具有對bundle ID的先驗知識(注:這里的先驗知識是指推理bundle ID的分派情況,參見 http://www.importanceofphilosophy.com/Irrational_APriori.html)。 為了提供一個更靈活的方法給一個Admin Permission指派bundle,Permission Admin必須給AdminPermission對象的生成提供特殊的來自PermissionInfo對象的支持。當一個Permission Info指定了一個Admin Permission,Permission Info的name參數必須是一個過濾器字符串,這個過濾器與OSGi過濾器具有相同的語法,只是路徑和簽名者屬性中的通配符具有特殊的規則。

          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 require
          AdminPermission[*,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 閱讀(1227) 評論(0)  編輯  收藏 所屬分類: OSGi

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          free counters
          主站蜘蛛池模板: 滕州市| 井冈山市| 屯昌县| 华安县| 章丘市| 蒙阴县| 阳高县| 邯郸县| 东山县| 金沙县| 清原| 望都县| 保靖县| 临高县| 西盟| 长治市| 鸡西市| 象山县| 临澧县| 郎溪县| 汪清县| 太仆寺旗| 剑阁县| 汝南县| 灵璧县| 台州市| 宁城县| 探索| 马公市| 团风县| 太湖县| 隆化县| 洪湖市| 义乌市| 扶绥县| 大石桥市| 英山县| 西安市| 凉山| 宁武县| 怀化市|