随笔 - 1  文章 - 37  trackbacks - 0
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

留言簿(16)

随笔分类

随笔档案

文章分类

文章档案

test

搜索

  •  

最新评论

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-04-17 13:12 Phrancol Yang 阅读(1367) 评论(0)  编辑  收藏 所属分类: OSGI

只有注册用户登录后才能发表评论。


网站导航: