114 Deployment Admin Specification

114.1 Introduction

The ability to install new software components after the time of manufacture is of increasing interest to manufacturers, operators, and end users. End users already are, or soon will be, accustomed to installing applications or services on their devices from remote servers.

The OSGi Framework provides mechanisms to manage the lifecycle of bundles, configuration objects, and permission objects, but the overall consistency of the runtime configuration is the responsibility of the management agent. In other words, the management agent decides to install, update, or uninstall bundles, create or delete configuration or permission objects, and manage other resource types.

The task of the management agent is extensive because it must track the sometimes fine-grained dependencies and constraints between the different resource types. This model, though extremely flexible, leaves many details up to the implementation significantly hindering the interoperability of devices because it does not unify the management aspects from the management systems point of view. This specification, therefore, introduces the Deployment Admin service that standardizes the access to some of the responsibilities of the management agent: that is, the life-cycle management of interlinked resources on an OSGi Framework. The role of the Deployment Admin service is depicted in Figure 114.1.

Figure 114.1 Deployment Admin role

Deployment Admin role

114.1.1 Essentials

  • Installing/Uninstalling - Provide a Deployment Package concept to install and uninstall bundles and related resources on an OSGi Framework as an atomic unit.

  • Tamper Detection - Provide detection of changes to a Deployment Package.

  • Securing - Provide a security model that allows Operators to control the Deployment Packages that are installed on an OSGi Framework.

  • Media Independence - Deployment Packages must have the capacity to load from different media such as CD-ROM, over the air, wireless, etc.

  • Management - Management of a repository of Deployment Packages must be possible locally on the device as well as remotely.

  • Customizing - The author of a Deployment Package must be permitted to customize the environment during the installation and uninstallation operations.

  • Extending - The resource types that are used in a Deployment Package must be easy to extend.

114.1.2 Entities

  • Resource - A file in a Deployment Package that is processed to create artifacts in the Framework. For example, bundles, configurations, and permissions are different resources.

  • Deployment Admin Service - The service that is used to install and uninstall Deployment Packages, as well as to provide information about the repository of Deployment Packages.

  • Resource Processor - A service that can handle the lifecycle of a specific resource type. It processes a resource to create a number of artifacts that are removed when the resource is dropped.

  • Deployment Package - A group of resources that must be treated as a unit. Unbreakable dependencies exist among these resources.

  • Artifact - A construct that is created from a Resource in a Deployment Package. A resource can have zero or more artifacts related to it. Artifacts do not have a common interface because their nature differs and their existence is abstracted by the Resource Processor services. Artifacts must be removed when their related resources are dropped. An example of an artifact is a Configuration object that is created from an configuration file in a Deployment Package.

  • Customizer - A bundle carried in a Deployment Package that can perform initialization during an install operation and cleanup during an uninstall operation.

  • Fix Package - A Deployment Package that is an update to an resident Deployment Package, which does not carry some resources because they are unchanged.

Figure 114.2 Deployment Admin Service, org.osgi.service.deploymentadmin package

Deployment Admin Service, org.osgi.service.deploymentadmin package

114.1.3 Synopsis

A developer can package a number of resources in a Deployment Package. A Deployment Package is stored in a JAR file, with a format that is similar to bundles. A Deployment Package JAR can be installed via the Deployment Admin service via an input stream. The Deployment Admin service manages the bundle resources itself, but processes every other resource in the Deployment Package by handing them off to a Resource Processor service that is designated for that resource. The Resource Processor service will then process the resource to create a number of artifacts.

The uninstallation and update of a Deployment Package works in a similar manner. All Resource Processor services are notified about any resources that are dropped or changed.

If all resources have been processed, the changes are committed. If an operation on the Deployment Admin service fails, all changes are rolled back. The Deployment Admin service is not, however, guaranteed to support all features of transactions.

114.2 Deployment Package

A Deployment Package is a set of related resources that need to be managed as a unit rather than individual pieces. For example, a Deployment Package can contain both a bundle and its configuration data. The resources of a Deployment Package are tightly coupled to the Deployment Package and cannot be shared with other Deployment Packages.

A Deployment Package is not a script that brings the system from one consistent state to another; several deployment packages may be needed to achieve a new consistent state. Like a bundle, a Deployment Package does not have to be self-contained. Its bundle resources can have dependencies on Java packages and services provided by other Deployment Packages.

For example, a suite of games shares some parts that are common to both games. The suite contains two games: Chess (com.acme.chess) and Backgammon (com.acme.backg). Both share a top-score database as well as a 3D graphic library.

  • com.third.3d - The 3D graphic library comes from a third-party provider. It is a Deployment Package of its own, composed of several bundles and possible configuration objects.

  • com.acme.score - The top-score database would also be its own Deployment Package, and would in fact be optional. It offers a service for storing top scores, but games can function without this service.

Each game is a Deployment Package, allowing them to be installed independently. Alternatively, the two games can be packaged into the same Deployment Package, but in this case they must be installed and removed together and can no longer be deployed independently.

These two different packaging strategies cannot be used simultaneously. Once the games are deployed separately, they can no longer be grouped later in an update, because that action would move ownership of the bundle resource to another Deployment Package which is specifically not allowed. A bundle resource can belong to only one Deployment Package.

These two packaging scenarios are depicted in Figure 114.3.

Figure 114.3 Packaged game

Packaged game

Deployment Packages are managed as first-class citizens during runtime, similar to bundles. The DeploymentPackage object represents this concept in runtime.

114.2.1 Resources

A Deployment Package consists of installable resources. Resources are described in the Name sections of the Manifest. They are stored in the JAR file under a path. This path is called the resource id.

Subsets of these resources are the bundles. Bundles are treated differently from the other resources by the Deployment Admin service. Non-bundle resources are called processed resources.

Bundles are managed by the Deployment Admin service directly. When installing a new bundle, the Deployment Admin service must set the bundle location to the following URL:

location ::= 'osgi-dp:' bsn
bsn      ::= unique-name     // See General Syntax Definitions in Core

The bsn stands for the bundle's Bundle Symbolic Name, without any parameters, which implies that only a single version of a bundle can be installed at any moment in time. The osgi-dp: scheme is not required to have a valid URL handler.

Processed resources are not managed directly by the Deployment Admin service; their management must be handed off to a Resource Processor service that is selected in the Name section. The logical structure and processing of resources is depicted in Figure 114.4.

Figure 114.4 Structure of a Deployment Package

Structure of a Deployment Package

114.2.2 Atomicity and Sharing

A Deployment Package is a reified concept, like a bundle, in an OSGi Framework. It is created and managed by the Deployment Admin service. As a unit, a Deployment Package should be installed or uninstalled atomically.

Deployment packages provide an ownership model for resources installed in an OSGi Framework. A Deployment Package contains resources, which once processed, will result in the creation of a number of artifacts in the OSGi Platform such as:

  • Installed bundles

  • Configuration objects

  • System properties

  • Certificates

  • Wiring schemes

A Deployment Package will own its resources. If a Deployment Package is uninstalled, all its resources, and thus its artifacts, must be removed as well. The ownership model follows a no-sharing principle: equal resources are not shared between deployment packages.

The meaning of "equal" is dependent on the resource type. For example, two bundles are considered equal if their bundle symbolic name is equal, regardless of the version.

A sharing violation must be considered an error. The install or update of the offending Deployment Package must fail if a resource would be affected by another Deployment Package. The verification of this rule is delegated to the Resource Processor services, or the Deployment Admin service in case of bundles.

For example, a Deployment Package could be used to install bundles and configuration objects for Managed Services (singleton configurations). Because of the no-sharing principle, an installed bundle must belong to one, and only one, Deployment Package (as defined by its Bundle Symbolic Name). A singleton configuration can be set only when the associated bundle is in the same Deployment Package. Trying to install a Deployment Package when one of the bundles or one of the configuration objects is already present and associated with another Deployment Package is an error, and the install must fail in such a case.

This strong no-sharing rule ensures a clean and robust lifecycle. It allows the simple cleanup rule: the Deployment Package that installs a resource is the one that must uninstall it.

114.2.3 Naming

Every Deployment Package must have a name and a version. Package authors should use unique reverse domain naming, like the naming used for Java packages. The version syntax must follow the rules defined in Version in OSGi Core Release 7; the version must be specified.

The name is set with a Manifest header. This name is used to detect whether an install is an update (an Deployment Package has the given name) or an install (no such Deployment Package exists). The name must be compared in a case-sensitive manner.

Together, the name and version specify a unique Deployment Package; a device will consider any Deployment Package with the same name and version pairs to be identical. Installing a Deployment Package with a name version identical to the existing Deployment Package must not result in any actions.

Deployment packages with the same name but different versions are considered to be versions of the same deployment package. The Deployment Admin service maintains a repository of installed Deployment Packages. This set must not contain multiple versions of the same Deployment Package. Installing a deployment package when a prior or later version was already present must cause replacement of the existing deployment package. In terms of version, this action can be either an upgrade or downgrade.

114.3 File Format

A Deployment Package is a standard JAR file as specified in [1] JAR File Specification. The extension of a Deployment Package JAR file name should be .dp. The MIME type of a Deployment Package JAR should be:

application/vnd.osgi.dp

For example, valid Deployment Package JAR names are:

com.acme.chess.dp
chess.dp

A Deployment Package must be formed in such a way that it can be read with a JarInputStream object. Therefore, the order of the files in the JAR file is important. The order must be:

  1. META-INF/MANIFEST.MF - A Deployment Package must begin with a standard Java Manifest file. This rule is not explicitly defined in the Java JAR file specification; it is implied, however, by the known JarInputStream class implementations.

  2. META-INF/*.SF, META-INF/*.DSA, META-INF/*.RS - If the Deployment Package is signed, subsequent files in the JAR must be the signature files as defined in the manifest specification. The signature files are not considered resources. Signing is discussed in Signing.

  3. Localization files - Any manifest localization files are normally stored in the OSGI-INF directory. Localization files must precede the other files because the resource processors can require localized information.

  4. Bundles must come before any other resource types so that they can be installed before any processed resources.

  5. Resources - Any processed resources needed for this package. Resources are processed in the order in which they appear in the JAR file, and dropped in reverse order.

The order of all the resources in the JAR file is significant, and is called the resource order. The purpose of the resource order is to allow the JAR to be processed as a stream. It is not necessary to buffer the input stream in memory or to hard disk, or to allow random access to its contents. The specification allows access to the stream sequentially. To increase the determinism, the resource order must also determine the processing order of the bundles and the resources.

The format is shown graphically in Figure 114.5.

Figure 114.5 Deployment Package JAR format

Deployment Package JAR format

114.3.1 Signing

Deployment packages are optionally signed by JAR signing, compatible with the operation of the standard java.util.jar.JarInputStream class, i.e. as defined in JAR Structure and Manifest of OSGi Core Release 7. This compatibility requires that the manifest must be the first file in the input stream, and the signature files must follow directly thereafter.

A Deployment Package must follow the same rules for signing as bundles, described in the Framework specification, Digitally Signed JAR Files in OSGi Core Release 7.

The Deployment Admin service must reject a Deployment Package that has an invalid signature.

114.3.2 Path Names

Path names must be limited to remove some of the unnecessary complexities that are caused by path names that can contain any Unicode character. Therefore, a path name must not contain any character except:

[A-Za-z0-9_.-]

Directories are separated by a solidus character ('/' \u002F).

114.3.3 Deployment Package Manifest

The Manifest of a Deployment Package consists of a global section and separate sections for each resource contained within it, called the Name sections. The global section of a Deployment Package Manifest can contain the following headers that have a defined meaning in this specification:

  • DeploymentPackage-SymbolicName - The name of the deployment package as a reverse domain name. For example, com.acme.chess. See further DeploymentPackage-SymbolicName.

  • DeploymentPackage-Version - The version of the deployment package as defined in OSGi Core Release 7. See further DeploymentPackage-Version.

  • DeploymentPackage-FixPack - Marks this deployment package as a partial update to a resident deployment package. See Fix Package.

The following headers provide information about the Deployment Package, but are not interpreted by the Deployment Admin service.

  • DeploymentPackage-Name - A human readable of this deployment package. This name can be localized.

  • DeploymentPackage-Copyright - Specifies the copyright statement for this Deployment Package.

  • DeploymentPackage-ContactAddress - How to contact the vendor/developer of this Deployment Package.

  • DeploymentPackage-Description - A short description of this Deployment Package.

  • DeploymentPackage-DocURL - A URL to any documentation that is available for this Deployment Package. The URL can be relative to the JAR file.

  • DeploymentPackage-Icon - A URL to an image file that is an icon for this deployment package. The URL can be relative to the JAR file.

  • DeploymentPackage-Vendor - The vendor of the Deployment Package.

  • DeploymentPackage-License - A URL to a license file. The URL can be relative to the Deployment Package JAR file.

  • DeploymentPackage-RequiredStorage - The minimum amount of persistent storage required by the deployment package after successful install or update.

As with any JAR file Manifest, additional headers can be added and must be ignored by the Deployment Admin service. If any fields have human readable content, localization can be provided through property files as described in Localization in OSGi Core Release 7. The Deployment Admin service must always use the raw, untranslated version of the header values.

For example, the global section of a Deployment Package Manifest could look like:

Manifest-Version: 1.0
DeploymentPackage-SymbolicName: com.third._3d
DeploymentPacakge-Version: 1.2.3.build22032005
DeploymentPackage-Copyright: ACME Inc. (c) 2003

Additionally, the Deployment Package Manifest must carry a Name section for each resource in the JAR file (except the resources in the META-INF directory). Each name section must start with an empty line (carriage return and line feed, shown as when its usage could be ambiguous).

The Name section must start with a Name header that contains the path name of the resource. This path name is also used as resource id. The path name must be constructed with the characters as defined in Path Names. For example:

Name: bundles/3dlib.jar

The name section can include any additional relevant meta data for the named resource. For bundles, only the specification of the Bundle-SymbolicName and Bundle-Version headers are required, but other headers can be added. Unrecognized headers are allowed and must be ignored by the Deployment Admin service. The Name section is also used by the JAR signing to include digests of the actual resources.

The following headers are architected for the Name section in the manifest of a deployment package:

  • Bundle-SymbolicName - Only for bundle resources. This header must be identical to the Bundle Symbolic Name of the named bundle. If there is a discrepancy, the install of the Deployment Package must fail. If the bundle resource has no Bundle-SymbolicName in its manifest, however, the Deployment Admin must use the given symbolic name for the calculation of the location of this bundle.

  • Bundle-Version - Only for bundle resources. This header must be identical to the bundle version of the named bundle. Its syntax must follow the version syntax as defined in the Framework specification. The installation must fail if incorrect.

  • DeploymentPackage-Missing - (true|false) Indicates that the resource is logically part of the Deployment Package but that a previous version of the Deployment Package already contained this resource there is no data for this resource. See Fix Package for a further explanation.

  • Resource-Processor - The PID of the Resource Processor service that must install the given resource.

  • DeploymentPackage-Customizer - (true|false) Indicates whether this bundle is a customizer bundle by listing a PID for the customizer service. See a further discussion in Customizer.

An example Manifest of a Deployment Package that deploys the 3D package, consisting of two bundles and no resources, could look like:

Manifest-Version: 1.0
DeploymentPackage-Icon: %icon
DeploymentPackage-SymbolicName: com.third._3d
DeploymentPacakge-Version: 1.2.3.build22032005

Name: bundles/3dlib.jar
SHA-1-Digest: MOez1l4gXHBo8ycYdAxstK3UvEg=
Bundle-SymbolicName: com.third._3d
Bundle-Version: 2.3.1

Name: bundles/3dnative.jar
SHA-1-Digest: N8Ow2UY4yjnHZv5zeq2I1Uv/+uE=
Bundle-SymbolicName: com.third._3d.native
Bundle-Version: 1.5.3

Name: OSGI-INF/autoconf.xml
SHA-1-Digest: M78w24912HgiZv5zeq2X1Uv-+uF=
Resource-Processor: org.osgi.deployment.rp.autoconf

114.3.4 Deployment Package Headers

This section contains a detailed description of the different headers for a Deployment Package with their value syntax.

114.3.4.1 DeploymentPackage-SymbolicName

The name of the deployment package. A name must follow the same rules as Java packages. The grammar is as follows:

DeploymentPackage-SymbolicName ::= unique-name 
                               // See General Syntax Definitions in Core

This header is mandatory and must not be localized.

An example is:

DeploymentPackage-SymbolicName: com.acme.chess

114.3.4.2 DeploymentPackage-Version

This header defines the version of the deployment package. The syntax follows the standard OSGi Framework rules for versions.

DeploymentPackage-Version ::= version    // See Version in Core

This header is mandatory and must follow the syntax of the version. It must not be localized.

An example:

DeploymentPackage-Version: 1.2.3.build200501041230

114.3.4.3 DeploymentPackage-FixPack

A fix package can be distinguished from the full format Deployment Package through the presence of the DeploymentPackage-FixPack header, contained within the global section of the Manifest. The format of this header is:

DeploymentPackage-FixPack ::= version-range 
                          // See Version Range in Core

The version range syntax is identical to the Framework module's layer version range as defined in OSGi Core Release 7. For example, a Manifest header that denotes a fix package which is only applicable to versions 1.3 through 3.4 of a given deployment package looks like:

DeploymentPackage-FixPack: [1.3,3.4]

See Fix Package for more information about Fix Packages.

114.3.4.4 DeploymentPackage-Icon

This header contains a URL (absolute or relative to the JAR file) to an image resource that represents this deployment package. Implementations should support at least the HTTP protocol as well as the PNG image file. This URL can be localized. The Deployment Admin service must maintain a local copy of the image resource. A URL to this local resource can be obtained with the getIcon() method.

DeploymentPackage-Icon ::= url
url ::= <absolute or relative URL or localization name>

For example:

DeploymentPackage-Icon: %icon

114.3.4.5 DeploymentPackage-Name

This header is available as the DeploymentPackage getDisplayName method. It provides a human readable name that can be localized. It is available through the getDisplayName() method. This name can be localized.

DeploymentPackage ::= name
name              ::= <any value or a localization name>

Example:

DeploymentPackage: 3D-Library

114.3.4.6 DeploymentPackage-RequiredStorage

This header specifies the minimum amount of persistent storage required by the deployment package after successful install or update. The value is an integer that represent kilo-bytes. The value includes the size of the bundles and any persistent storage needs and storage needed to run the resource processors and customizers. An installation agent can verify the availability of sufficient memory before installing the package. A fix-pack must specify the minimum memory requirements of the complete deployment package after the it is applied.

DeploymentPackage-RequiredStorage ::= number

Example

DeploymentPackage-RequiredStorage: 15

114.3.4.7 Bundle-SymbolicName (Name Section)

The Bundle-SymbolicName header must be a copy of the Bundle-SymbolicName header in the named bundle, including any parameters. This header must match the Bundle-SymbolicName of the actual bundle; if it does not, the install or update must fail. The parameters, however, can differ between updates. The header has the following format:

Bundle-SymbolicName: unique-name (';' parameter) *

If the bundle resource has no Bundle-SymbolicName header, the given symbolic name must be used to calculate the location of the bundle.

For example:

Name: bundles/http.jar
Bundle-SymbolicName: com.acme.http; singleton=true

114.3.4.8 Bundle-Version (Name Section)

The Bundle-Version header must be equal to the Bundle-Version header in the named bundle. It must follow the format as defined for the version clause in OSGi Core Release 7.

Bundle-Version ::= version     // See Version in Core

A mismatch between the version indicated in the Manifest of the Deployment Package and the actual value in the Bundle's Manifest must cause an installation or update to fail.

For example

Bundle-Version: 1.2

114.3.4.9 Resource-Processor (Name Section)

The Resource-Processor header selects an OSGi Resource Processor service for this resource by selecting the Resource-Processor service with the given PID as service.id service property. This header is optional, so that the Deployment Package can carry resources that are not processed: for example, license and documentation files. The format of the header is:

Resource-Processor ::= pid     // See General Syntax Definitions in Core

For example:

Name: certificate/certificates.xml
SHA-1-Digest: M78w249126182Ak5zeq2X1Uv-+uF=
Resource-Processor: com.securitas.keystore

In the example, the certificates.xml in the certificate directory will be processed by the Resource Processor service registered with the service property service.pid set to com.securitas.keystore. The service.pid is a standard Framework property to uniquely identify a service instance called a Persistent IDentity a.k.a. PID.

114.3.4.10 DeploymentPackage-Missing (Name Section)

Fix packs (see Fix Package ) are Deployment Packages that do not contain all the resources for a full install. This header indicates the Bundle Symbolic Name of a bundle that is not present in the enclosing JAR file but should be part of a prior version of this Deployment Package. The format is:

DeploymentPackage-Missing ::= 'true' | 'false'

The default value for this header is false. An error results if this header is true and the resource is not present in the existing Deployment Package.

For example:

Name: bundles/3dlib.jar
DeploymentPackage-Missing: true
Bundle-SymbolicName: com.acme.http
Bundle-Version: 3.0

114.3.4.11 DeploymentPackage-Customizer (Name Section)

This header is used to indicated that a resource is a customizer bundle, as described in Customizer. The syntax of this optional header is:

DeploymentPackage-Customizer ::= 'true' |'false'

The default for this header is false.

For example:

Name: bundles/3dlibcustomizer.jar
DeploymentPackage-Customizer: true
Bundle-SymbolicName: com.acme.customizer
Bundle-Version: 3.6

114.3.5 Localization

All human readable headers can be localized using the same mechanism as is used to localize the manifest of a bundle. This mechanism is described in Localization of the OSGi Core Release 7.

For example, a Manifest could look like:

Manifest-Version: 1.0
DeploymentPackage-ManifestVersion: 1
DeploymentPackage-SymbolicName: com.third._3d
DeploymentPacakge-Version: 1.2.3.build22032005
DeploymentPackage-Copyright: %copyright
DeploymentPackage-Vendor: %vendor
DeploymentPackage-License: %licenseurl
DeploymentPackage-Description: %3dlib
DeploymentPackage-Icon: %iconurl
DeploymentPackage-Name: %name
Bundle-Localization: OSGI-INF/l10n/dp

Name: bundles/3dlib.jar
SHA-1-Digest: MOez1l4gXHBo8ycYdAxstK3UvEg=
Bundle-SymbolicName: com.third._3d
Bundle-Version: 2.3.1

Name: OSGI-INF/autoconf.xml
SHA-1-Digest: M78w24912HgiZv5zeq2X1Uv-+uF=
Resource-Processor: org.osgi.deployment.rp.autoconf

Name: icon_nl.gif
SHA-1-Digest: n72w21124hGiZV5zQeAXxUvaaUf=

Name: OSGI-INF/l10n/dp.properties
SHA-1-Digest: V5zQeAXxUvaaUfn72w21124hGiZ=

Name: OSGI-INF/l10n/dp_nl.properties
SHA-1-Digest: xUvaaUfn72w21124hGiZV5zQeAXx

Different language translations can be provided, such as:

OSGI-INF/l10n/dp.properties:
copyright=ACME Inc. (c) 2005
vendor=ACME Inc.
license=OSGI-INF/license.en.txt
3dlib=High performance graphic library
name=3D-Lib
icon=htpp:/www.acm.com/3dlib/icon.gif

OSGI-INF/l10n/dp_nl.properties:
copyright=ACME Holland BV (c) 2005
vendor=ACME Holland BV.
license=OSGI-INF/licentie.txt
3dlib=Zeer snelle 3D grafische routine bibliotheek
icon = icon_nl.gif
name = 3D-Bibliotheek

The language translation resources should appear in the Name section of the manifest so they can be signed.

114.4 Fix Package

A Fix Package is a Deployment Package that minimizes download time by excluding resources that are not required to upgrade or downgrade a Deployment Package. It can only be installed on a Framework if a previous version of that Deployment Package is already installed. The Fix Package contains only the changed and new resources. A Fix Package (called the source) therefore must specify the range of versions that the existing Deployment Package (called the target) must have installed. This range is specified with the DeploymentPackage-FixPack header in the manifest of the source.

The Manifest format for a Fix Package is, except for the Fix Package header, the same as for a Deployment Package manifest: each resource must be named in the Name section of the Manifest. Resources that are absent, however, must be marked in the named section with the DeploymentPackage-Missing header set to true.

Thus, the name sections of the manifest of a Fix Package must list all resources, absent or present, in order to distinguish between resources that must be removed or resources that are absent. Name sections that specify the DeploymentPackage-Missing header, however, indicate that the actual content of the resource is not carried in the Deployment Package. That is, the resource content is absent. Only a Fix Package is permitted to contain the DeploymentPackage-Missing headers.

For example, the following headers define a valid Fix Package that can update an existing Deployment Package, only if the version is between 1 and 2.

Manifest-Version: 1.0
DeploymentPackage-SymbolicName: com.acme.package.chess
DeploymentPackage-Version: 2.1
DeploymentPackage-FixPack: [1,2)

Name: chess.jar
Bundle-SymbolicName: com.acme.bundle.chess
DeploymentPackage-Missing: true
Bundle-Version: 5.7

Name: score.jar
Bundle-SymbolicName: com.acme.bundle.chessscore
Bundle-Version: 5.7

In this example, the Fix Package requires that version 1.x.y of the deployment package is already installed. The presence of the com.acme.bundle. chess bundle on the Framework is assumed, and it must be part of the existing Deployment Package com.acme.package.chess. After installation, this Deployment Package must contain the two listed bundles.

114.5 Customizer

The standardized Deployment Admin service installation and uninstallation functions do not always cover the needs of a developer. In certain cases, running custom code at install and uninstall time is required. This need is supported with the Deployment Package Customizer. Typical Customizer bundles are:

  • Database initialization

  • Data conversion

  • Wiring

A Customizer bundle is indicated by a DeploymentPackage-Customizer header in a Name section for a bundle resource. A Deployment Package can have a number of customizers, or none. A Customizer bundle must be installed and started by the Deployment Admin service before any of the resources are processed.

As a Customizer bundle is started, it should register one or more Resource Processor services. These Resource Processor services must only be used by resources originating from the same Deployment Package. Customizer bundles must never process a resource from another Deployment Package, which must be ensured by the Deployment Admin service.

Customizers are installed and started in the order that they appear in the Deployment Package.

114.5.1 Bundle's Data File Area

Each bundle in the OSGi Framework has its own persistent private storage area. This private area is accessed by a bundle with the getDataFile method on the Bundle Context. The location in the file system where these files are stored is not defined, and thus is implementation-dependent. A Customizer bundle, however, typically needs access to this private storage area.

The Deployment Admin service provides access to the Bundle private storage area with the getDataFile(Bundle) method on the DeploymentSession object. This method returns a File object to the root of the data directory.

The location of a bundle's private storage area is impossible to determine because it depends on the implementation of the OSGi Framework. It is therefore impossible to give a Customizer bundle an appropriate File Permission for customization of a bundle's data area.

Therefore, if a Customizer bundle calls the getDataFile method for a specific bundle, the Deployment Admin must add to the Customizer bundle the required File Permission to access this area. This File Permission must be removed after the session ends.

114.5.2 Customizers and Update

The lifecycle of a customizer bundle is intertwined with the lifecycle of the resources it processes. Care should be taken to ensure that updates and uninstallations are handled correctly. A Customizer bundle is updated before a resource is processed implying that a deployment session n is always dropped or processed by the customizer from session n+1. In this case, a session is an install or uninstall of a Deployment or Fix Package.

Figure 114.6 Time line for customizer versus resource versions

Time line for customizer versus resource versions

In Figure 114.6, Customizer bundle 2.0 must update the resource from version 1.0, and customizer 3.0 must drop the resource from version 2.0. As a consequence, the Customizer bundle that processes a resource will be a different version than the one that processes or drops it.

The same ordering issue is also relevant with respect to the Autoconf resources (see Auto Configuration Specification ). Autoconf resources will not be available until the commit method is called. This condition implies that a customizer cannot receive fresh configuration information from the Deployment Package.

114.6 Deployment Admin Service

The Deployment Admin service provides the following services:

  • Introspecting - Provide information about the Deployment Package repository. Introspecting is further discussed on Introspection.

  • Install - The installation of a Deployment Package is described in Installing a Deployment Package.

  • Uninstall - The uninstallation of a Deployment Package is described in Uninstalling a Deployment Package.

  • Canceling - An ongoing session can be canceled with the cancel method described in Canceling.

An important concept of the Deployment Admin service is the session. Installations and uninstallations of Deployment Packages take place inside a session. This session is represented by a DeploymentSession object. The session provides access to the Deployment Package that is being (un)installed, as well as access to the data area of bundles. The transactional aspects of this sessions are discussed in Sessions.

114.6.1 Introspection

The Deployment Admin service can provide the list of currently installed Deployment Packages with the listDeploymentPackages() method. Given a name, it is also possible to get a Deployment Package with getDeploymentPackage(String) using the name, or getDeploymentPackage(Bundle) for the Deployment Package of a specific bundle.

The listDeploymentPackages() method returns an array of DeploymentPackage objects. This list of Deployment Packages must contain only valid installed packages. During an installation or upgrade of an existing package, the target must remain in this list until the installation process is complete, after which the source replaces the target. If the installation fails, the source must never become visible, even transiently.

DeploymentPackage objects provide access to the following identity information:

The Deployment Package also provides access to the bundles that are associated with a Deployment Package.

  • getBundleInfos() - Returns an array of information about all bundles that are owned by this Deployment Package. The return type is a BundleInfo object that has a getVersion() and getSymbolicName() method.

  • getBundle(String) - Returns the bundle with the given Bundle Symbolic Name that is associated with this Deployment Package. As this instance is transient, for example, a bundle can be removed at any time because of the dynamic nature of the OSGi platform, this method may also return null if the bundle is part of this deployment package but is temporarily not defined in the Framework.

The Deployment Package also provides access to the headers in its Manifest. The global section and the Name sections are both supported. This information can be used to provide human-readable information to the end user. If the Manifest is using localization, this information must be returned in the default locale. It is not possible to specify a specific locale. See Localization for more information.

  • getHeader(String) - Provides access to the Deployment Package's Manifest header global section. Header names must be matched in a case-insensitive manner.

  • getResourceHeader(String,String) - Provides access to a header in the Name section. The first argument specifies the resource id (JAR path); the second argument is the (case insensitive) header name.

The Deployment Package contains a number of resources. Each resource can be queried for its associated Resource Processor service.

  • getResourceProcessor(String) - Return the Service Reference of the Resource Processor service that is associated with the given resource. For a Bundle resource, the returned Resource Processor must be null.

  • getResources() - Return an array of resource names. This array must include the Bundle resources.

The isStale() method returns true when DeploymentPackage object is no longer available.

114.6.2 Canceling

An ongoing session can be canceled with the Deployment Admin service's cancel() method. This method must find the currently executing Resource Processor service and call its cancel method. The remainder of the session must be immediately rolled back after the Resource Processor returns from the active method.

114.7 Sessions

The (un)installation or upgrade of a deployment package requires the cooperation and interaction of a large number of services. This operation, therefore, takes place in a session. A session must be created by the Deployment Admin service before any activity on behalf of the Deployment Package takes place, including any bundle installations. Sessions are not visible to the clients of Deployment Admin service.

Before using a resource processor in a session, the Deployment Admin service must join the Resource Processor service to the session. The begin(DeploymentSession) method must be called before a Resource Processor service calls the process, drop, or dropAllResources method. For brevity, this joining is not shown in the following sections, but must be assumed to have taken place before any of the methods is called.

A Resource Processor has joined the session when it has returned from its begin(DeploymentSession) method without an Exception being thrown. A Resource Processor service must not be joined to more than a single session at any moment in time implying that a Resource Processor can assume that only one install takes place at a time.

A roll back can take place at any moment during a session. It can be caused by a Resource Processor service that throws an Exception during a method call, or it can be caused by canceling the session (see Canceling ).

If all methods in a session are executed without throwing Exceptions, then the session must be committed. Commitment first requires a vote about the outcome of the session in the so-called prepare phase. The Deployment Admin service must therefore call the prepare method on all Resource Processor services that have joined the session. The Resource Processor services must be called in the reverse order of joining.

Any Resource Processor that wants to roll back the session in the prepare phase can, at that moment, still throw an Exception. The prepare method can also be used to persist some of the changes, although the possibility remains that the session will be rolled back and that those changes must then be undone.

If all joined Resource Processors have successfully executed the prepare method, the Deployment Admin service must call the commit method on all Resource Processor services that have joined the session. The Resource Processor services must be called in the reverse order of joining. Resource Processor services must not throw an Exception in this method; they should only finalize the commit. Any Exceptions thrown should be logged, but must be ignored by the Deployment Admin service.

114.7.1 Roll Back

At the moment of the roll back, a number of Resource Processor services can have joined the session and bundles could have been installed. For each of these joined Resource Processor services, the Deployment Admin service must call the rollback() method. A roll back can be caused by a thrown Exception during an operation, or can be initiated by the caller. The roll back can even happen after the prepare() method has been called if another Resource Processor throws an Exception in its prepare method. The Resource Processor services must be called in the reverse order of joining for the rollback method.

The system should make every attempt to roll back the situation to its pre-session state:

  • Changed artifacts must be restored to their prior state

  • New artifacts must be removed

  • Stale artifacts must be created again

  • Any installed or updated bundles must be removed

  • The state of the target bundles must be restored

If the target bundles were started before, and the state can be restored successfully, the target bundles must be refreshed and started again before the method returns.

If the roll back cannot completely restore the state of the target bundles, the target bundles that were restored must not be restarted, in order to prevent running bundles with incompatible versions. An appropriate warning should be logged in this case.

After the commit or rollback method, the DeploymentAdminSession object is no longer usable.

The transactional aspects of the session are depicted in Figure 114.7.

Figure 114.7 Transactional Sessions

Transactional Sessions

The Deployment Admin service must uninstall any new bundles and install stale bundles (bundles that were uninstalled during the session), and should roll back updated bundles. Rolling back a bundle update, as well as reinstalling a stale bundle, requires an implementation-dependent back door into the OSGi Framework, because the Framework specification is not transactional over multiple lifecycle operations. Therefore, this specification does not mandate full transactional behavior.

After a roll back, however, a Deployment Package must still be removable with all its resources and bundles dropped. A roll back must not bring the Deployment Package to a state where it can no longer be removed, or where resources become orphaned.

114.7.2 Bundle Events During Deployment

Deployment operations usually result in bundles being installed or uninstalled. These deployment operations can fail in mid-operation, and cause a roll back by Deployment Admin meaning that the platform can go through some transient states in which bundles are installed, then uninstalled due to roll back.

Therefore, the order of Bundle events produced by a transactional implementation must be compatible with the Bundle events produced by a non-transactional implementation. A transactional implementation, however, can choose to postpone all events while maintaining ordering until the end of the session and thereby canceling any events that cancel each other (e.g. install and uninstall). A non-transactional Deployment Admin service must send out the events as they occur.

In the following example, a simple Deployment Package consists of bundles A, B, and C. If this Deployment Package is successfully installed, an implementation must produce the following Bundle events (in order):

  1. BundleEvent(INSTALLED) for bundle A

  2. BundleEvent(INSTALLED) for bundle B

  3. BundleEvent(INSTALLED) for bundle C

If an operation of this Deployment Package was unsuccessful because, for example, Bundle C could not be installed due to an error, then the Deployment Admin service must roll back the deployment operation to return the platform to its original state. If the Deployment Admin service is transactional, then it must not expose the events because no persistent bundle changes were made to the platform.

On the other hand, a non-transactional implementation must expose the transient bundle states that occur during the deployment operation. In this case, the following bundle events could have been generated (in order):

  1. BundleEvent(INSTALLED) for bundle A

  2. BundleEvent(INSTALLED) for bundle B

  3. BundleEvent(UNINSTALLED) for bundle A

  4. BundleEvent(UNINSTALLED) for bundle B

114.8 Installing a Deployment Package

Installation starts with the installDeploymentPackage(InputStream). No separate function exists for an update; if the given Deployment Package already exists, it must be replaced with this new version. The purpose of the installDeploymentPackage method is to replace the target Deployment Package (existing) with the source Deployment Package (contained in the Input Stream).

The InputStream object must stream the bytes of a valid Deployment Package JAR; it is called the source deployment package. The InputStream object must be a general InputStream object and not an instance of the JarInputStream class, because these objects do not read the JAR file as bytes.

If an installed Deployment Package has the same name as the source, it is called the target Deployment Package. If no target exists, an invisible empty target with a version of 0.0.0 must be assumed without any bundles and resources.

The installation of a deployment package can result in these qualifications for any resource r:

  • r source, r target - New resource

  • r source, r target - Stale resource

  • r source, r target - Updated resource

The short scenario for an install is depicted in Figure 114.8.

Figure 114.8 Overview of install process

Overview of install process

In more detail, to install a Deployment Package, a Deployment Admin service must:

  1. Create a Deployment Session

  2. Assert that the Manifest file is the first resource in the Deployment Package JAR file.

  3. Assert the following:

    • The source must not contain any bundle that exists in other deployment packages, except for the target. The source bundles, as defined by the symbolic name, must belong to the target or be absent.

    If the source is a Fix Package, assert that:

    • The version of the target matches the required source version range.

    • All the missing source bundles are present in the target.

    Otherwise:

    • Assert that are no missing resources or bundles declared.

  4. Process the localization files, see Localization.

  5. All target bundles must be stopped in reverse target resource order. Exceptions thrown during stopping must be ignored, but should be logged as warnings.

The target is now stopped; none of its bundles are running any longer. The next step requires the sequential processing of the resources from the source JAR file in source resource order. The bundles must be processed first (if present), and can be followed by any number of resources, or none.

For each bundle read from the source JAR stream:

  1. If the bundle symbolic name already exists in the system with a different version number, update that bundle with the resource stream. If the version is identical, the resource stream must be ignored. The update method must follow the semantics of the OSGi Framework update method. An exception thrown during the update must roll back the session.

    Otherwise, install the bundle according to the semantics of the OSGi Framework installBundle method. The location of the bundle must be set to the Bundle Symbolic Name without any parameters and be prefixed with the osgi-dp: scheme. An exception thrown during the install must roll back the session.

    Framework events are discussed in Bundle Events During Deployment.

  2. Assert that the installed bundle has the Bundle Symbolic Name and version as defined by the source manifest. If not, the session must be rolled back.

All the source's bundles are now installed or updated successfully. Next, any customizers must be started so that they can participate in the resource processing:

  1. If Customizer bundles or stale customizers are defined, start them. If any Customizer bundle's start method throws an exception, the session must be rolled back.

For each resource read from the JAR stream:

  1. Find the Resource Processor service that processes the resource by using the PID in the Resource-Processor header. If it cannot be found, the session must be rolled back.

  2. Assert that the matched Resource Processor service is not from a Customizer bundle in another Deployment Package.

  3. Call the matched Resource Processor service process(String,InputStream) method. The argument is the JAR path of the resource. Any Exceptions thrown during this method must abort the installation.

All resource updates and installs have now occurred. The next steps must remove any stale resources. First the stale resources are dropped, and then the bundles are uninstalled. Exceptions are ignored in this phase to allow repairs to always succeed, even if the existing package is corrupted.

  1. In reverse target order, drop all the resources that are in the target but not in the source by calling the matching Resource Processor service dropped(String) method. Any exceptions thrown during this method should be logged as warnings, but must be ignored.

  2. Uninstall all stale bundles in reverse target order, using the OSGi Framework uninstall method semantics. Any exceptions thrown should be logged as warnings, but must be ignored.

The deployment package is now cleaned up, and can be activated and committed.

  1. All the Resource Processor services that have joined the session must now prepare to commit, which is achieved by calling the prepare() method. If any Resource Processor throws an Exception, the session must roll back. The Resource Processors must be called in the reverse order of joining.

  2. If all the Resource Processors have successfully prepared their changes, then all the Resource Processor services that have joined the session must now be committed, which is achieved by calling the commit() method. The Resource Processors must be called in the reverse order of joining. Any exceptions should be logged as warnings, but must be ignored.

  3. Refresh the bundles so that any new packages are resolved.

  4. Wait until the refresh is finished.

  5. Start the bundles in the source resource order. Exceptions thrown during the start must be logged, but must not abort the deployment operation.

The session is closed and the source replaces the target in the Deployment Admin service's repository.

The installDeploymentPackage method returns the source Deployment Package object.

114.8.1 Example Installation

The target Deployment Package has the following manifest:

Manifest-Version: 1.0
DeploymentPackage-SymbolicName: com.acme.daffy
DeploymentPackage-Version: 1

Name: bundle-1.jar
Bundle-SymbolicName: com.acme.1
Bundle-Version: 5.7

Name: r0.x
Resource-Processor: RP-x

Name: r1.x
Resource-Processor: RP-x

Name: r1.y
Resource-Processor: RP-y

This deployment package is updated with a new version, with the following manifest:

Manifest-Version: 1.0
DeploymentPackage-SymbolicName: com.acme.daffy
DeploymentPackage-Version: 2

Name: bundle-2.jar
Bundle-SymbolicName: com.acme.2
Bundle-Version: 5.7

Name: r1.x
Resource-Processor: RP-x

Name: r2.x
Resource-Processor: RP-x

Name: r1.y
Resource-Processor: RP-y

The delta between version 1 and version 2 of the com.acme.daffy Deployment Package is depicted in Figure 114.9. Bundle-1 must be uninstalled because it is no longer present in the Deployment Package com.acme.daffy version 2. Bundle-2 is a new bundle and thus must be installed. The resource r0.x must be dropped and r1.x must be updated (this must be detected and treated accordingly by Resource Processor RP-x). r2.x is a new resource. The resource r1.y is updated by Resource Processor RP-y).

Figure 114.9 Delta

Delta

The sequence diagram for the installation is shown in Figure 114.10.

Figure 114.10 Sequence Diagram for a Resource Processor

Sequence Diagram for a Resource Processor

114.9 Uninstalling a Deployment Package

Uninstalling a Deployment Package must remove all the effects of its installation(s). The uninstall is started by calling uninstall() or uninstallForced() method on a target DeploymentPackage object.

The Deployment Packages are uninstalled explicitly, which may break the overall runtime configuration. No attempt is made to ensure that the uninstalled Deployment Package is required as a provider of Java packages or services, or fulfills other dependencies.

The Deployment Admin service must take the following actions to remove the target Deployment Package when uninstall() is called. This procedure must run inside a Deployment Admin session. A Resource Processor that is called must first join the session as described in Sessions.

Uninstalling is composed of the following steps:

  1. Start a new Deployment Admin session.

  2. Stop all the bundles owned by the Deployment Package. If this step throws a Bundle Exception, this error should be logged but must be ignored.

  3. Call the dropAllResources() method on all the Resource Processor services that are owned by this Deployment Package. Absent Resource Processor services or Exceptions that are thrown must immediately roll back this session.

  4. Call the prepare method on the Resource Processor services that joined the session. If any Resource Processor service throws an Exception, the session must be rolled back.

  5. Call the commit method on the Resource Processors that joined the session.

  6. Uninstall all owned bundles.

Uninstalling a Deployment Package can break the overall runtime configuration. No attempt is made to ensure that a Deployment Package being uninstalled is not necessary as a provider of Java packages or services, or fulfills other dependencies.

An error condition results if the Resource Processor services are no longer present when uninstalling or updating a deployment package. A request to carry out an uninstall operation on such a Deployment Package must be refused until the Resource Processor services are all available. A means must be provided, however, to handle permanent unavailability of these services.

To address this issue, the DeploymentPackage interface provides a method, uninstallForced(), which forces removal of the Deployment Package from the repository maintained by the Deployment Admin service. This method follows the same steps described earlier. Any errors, or the absence of Resource Processor services, should be logged but ignored; they must not cause a roll back.

If errors occur or Resource Processor services are absent, it is likely that the uninstallation will be incomplete, and that some residual artifacts will remain on the platform. Whether this residue is eventually cleaned up, and how, is left up to the implementation.

114.10 Resource Processors

The Resource Processor service interprets the byte stream of a resource. Typically, the stream is parsed and its information is stored as artifacts. Examples of resource processors are:

  • Configuration Management - This processor is standardized by the OSGi and more information can be found in Auto Configuration Specification.

  • Certificate Keystore - A Certificate Keystore processor could extract certificates from a bundle and install them in a keystore.

  • SyncML Script - Execute a series of SyncML commands.

The Deployment Admin service maintains the list of resource ids (the path name in the JAR) that are contained in a Deployment Package. Each resource is uniquely identified within a Deployment Package by its path name hence the term "resource id." The Deployment Package's getResources() method provides a list of the resources ids.

The Resource Processor service is responsible for actually creating and deleting the resource related artifacts. The Resource Processor service must be able to remove the artifacts related to a resource that is being dropped using only the resource id.

The ResourceProcessor interface is based on a session (see Sessions ). The transactionality is limited to the bracketing of any processing or dropping of resources. The bracketing begins when a Resource Processor joins an install session. A Resource Processor service can assume that it is never in two sessions at the same time (see Threading ). It can, however, be called multiple times during the session to process different resources.

Before the Resource Processor service is used in an install or uninstall session, the Deployment Admin service must call the begin(DeploymentSession) method; this action makes the Resource Processor service join the session. This method must be used by the Resource Processor service to mark any changes for potential roll back, from this time until the prepare() / commit() or rollback() method is called.

When the session is opened, the Deployment Admin service can call the following methods on the Resource Processor service:

  • process(String,InputStream) - The Resource processor must parse the Input Stream and persistently associate the resulting artifacts with the given resource id. It must be possible to remove those artifacts in a future time, potentially after a complete system restart. Keep in mind that a resource can be processed many times. A Deployment Package that updates to a newer version is likely to contain the same resources again. Care should be taken to ensure that these updates are real updates and do not add new, unwanted artifacts.

  • dropped(String) - The artifacts that were associated with the given resource id must be removed. If the named resource does not exist, a warning should be logged but no Exception should be thrown.

  • dropAllResources() - Remove all artifacts that are related to the current target Deployment Package. This method is called when a Deployment Package is uninstalled.

  • cancel() - This method is called when the Resource Processor is in the process(String,InputStream), dropped(String) or dropAllResources() method, allowing the caller to cancel a long-running session. In that case, the Deployment Admin must call the cancel() method for the active Resource Processor service. The Resource Processor service should terminate its action as quickly as possible. The Resource Processor service must still handle a roll back of the session after it has returned.

All methods must perform any integrity checks immediately and throw an Exception with an appropriate code if the verification fails. These checks must not be delayed until the prepare or commit method. As stated earlier, changes must be recorded, but it should be possible to roll back the changes when the rollback method is called.

Deployment Packages can be upgraded or downgraded. Resource Processor services must therefore be capable of processing resources that have a lower, equal, or higher version.

114.10.1 Example Resource Processor

An example is a Resource Processor service that wires services with the Wire Admin service. The Wire Admin service creates wires between a producer and a consumer service, each identified by a PID. Wires are the artifacts that are installed and removed. Each wire contains a Dictionary object that is a convenient place to tag wires with the Deployment Package name and resource id. The Wire Admin stores this information persistently, which makes it very suitable for use in a transactional model. This small example supports full transactionality, although without crash recovery.

For simplicity, the wire definitions are stored in a format compatible with the java.util.Properties format (because it can simply be loaded from an Input Stream object). The key is the producer and the value is the consumer. A sample wiring could look like:

com.acme.gps = com.acme.navigation
com.acme.asn = com.acme.navigation
com.acme.navigation = com.acme.poi 

This wiring is depicted in Figure 114.11.

Figure 114.11 Sample Wiring

Sample Wiring

This resource is stored in a Deployment Package JAR file. In this example there are no bundles, so the Deployment Package's manifest would look like:

Manifest-Version: 1.0
DeploymentPackage-SymbolicName: com.acme.model.E45.wiring
DeploymentPackage-Version: 1.2832

Name: sample.wiring
Resource-Processor: wire.admin.processor

To reduce the size of the code in this example, the Wire Admin service is received as a parameter. The constructor registers the object as a Resource Processor service with the required wire.admin.processor PID.

The transaction strategy of this code is to create wires when new wires have to be created, but to delay the deletion of wires until the end of the session. Any created wires are kept in the createdWires field, and the wires that are to be deleted are kept in the toBeDeletedWires field.

The current DeploymentPackage object is saved in the current field when the begin method is called.

public class WireAdminProcessor implementsResourceProcessor {
    WireAdmin         admin;
    DeploymentPackage current;
    List              createdWires     = new Vector();
    List              toBeDeletedWires = new Vector();

    public WireAdminProcessor(
            WireAdmin admin, BundleContext context)
            throws Exception {
        this.admin = admin;
        Dictionary properties = new Hashtable();
        properties.put(Constants.SERVICE_PID,
                "wire.admin.processor");
            context.registerService(
                ResourceProcessor.class.getName(), this,
                properties);
    }

When the Deployment Admin service is installing a Deployment Package JAR, it must call the Resource Processor service's begin method before the first time it calls a Resource Processor service to join it to the current session. In this case, only the source DeploymentPackage object is saved in the current field.

    public void begin(DeploymentSession session){
        current = session.getSourceDeploymentPackage();
    }

The most complicated method that must be implemented is the process method. This method receives the resource id and an input stream with the contents. In this case, the stream is easily converted to a java.util.Properties object that contains the definitions of the wires.

The key and value of the Properties object are the producer and consumer respectively, which are used to create new wires. Each wire has a Dictionary object in the Wire Admin service. This Dictionary object is used to store the following properties:

  • deployment.package - The symbolic name of the current (target) deployment package. This property associates the wire with a specific deployment package.

  • resource.id - The resource id, or JAR path name. This id associates the specific resource with the wire.

Associating these fields with the wire simplifies finding all wires related to a Deployment Package or all wires related to a specific resource id and Deployment Package. The Wire Admin service supports a search method for wires that takes a filter as argument, further simplifying this process.

After a wire is created, it is stored in the createdWires list so that the wires can be deleted if the session is rolled back.

The process method looks as follows:

    public void process(String resourceId, InputStreamin) 
                throws Exception {
        Properties properties = new Properties();
        properties.load(in);
        Dictionary dict = new Hashtable();
        dict.put("deployment.package", current.getName());
        for (Iterator i = properties.values().iterator();
                i.hasNext();) {
            dict.put("resource.id", resourceId );
            String producer = (String) i.next();
            String consumer = properties.getProperty(producer);
            Wire wire = admin.createWire(producer, 
                consumer, dict);
            createdWires.add(wire);
        }
    }

If a resource is not in the source but is in the target Deployment Package, it must be dropped from the Resource Processor service. The Deployment Admin will call the dropped(String) method for those resources. Therefore, the wires that are tagged with the given resource id and Deployment Package name must be deleted.

The Wire Admin service has a convenient function to get all the wires that match a filter. This method is used to list all the wires that belong to the current Deployment Package as well as those that have the matching resource id. This array is added to the toBeDeletedWires field so that it can be deleted when the session is successfully completed. That is, wires are not deleted until the commit phase. When the session is rolled back, the list of wires to be deleted can be discarded, because they were never really deleted.

    public void dropped(String name) throws Exception{
        List list = getWires(
            "(&(resource.id=" + name + ")(deployment.package="
                + current.getName() + "))");
        toBeDeletedWires.addAll(list);
    }

If the session concludes without errors, the Deployment Admin service must call the prepare() method. In this example, it is possible to roll back the persistent changes made so far. The method can therefore just return.

    public void prepare() {}

The commit() method must now actually delete the wires that were removed during the session. After these wires are deleted, the method can throw away the list of wires that were created. This list was only kept to remove the wires in case of a roll back.

    public void commit() {
        delete(toBeDeletedWires);
        toBeDeletedWires.clear();
        createdWires.clear();
    }

The rollback() method is the reverse of the commit. Any created wires must now be deleted to undo their creations in this session. The wires that are to be deleted can now be discarded, because they have not been deleted yet and therefore do not have to be rolled back.

    public void rollback() {
        delete(createdWires);
        toBeDeletedWires.clear();
        createdWires.clear();
    }

The dropAllResources() method must drop all the wires that were created on behalf of the current Deployment Package. The filter on the getWires method makes this process very straightforward. Just delete all the wires that were tagged with the Deployment Package name.

    public void dropAllResources() {
        List list = getWires("(deployment.package=" 
            + current.getName() + ")");
        toBeDeletedWires.addAll(list);
    }

The cancel() method must cancel ongoing operations. This example does not have any long-running operations. The cancel method can therefore just return.

    public void cancel() {}

And finally, some helper methods should be self-explanatory.

    void delete(List wires) {
        while ( ! wires.isEmpty() )
            admin.deleteWire((Wire) wires.remove(0));
    }

    List getWires(String filter) {
        try {
            Wire[] wires = admin.getWires(filter);
            return Arrays.asList(wires);
        }
        catch (InvalidSyntaxException ise) {
            ise.printStackTrace();
        }
        return new Vector();
    }
}

This example is obviously not an "industrial-strength" implementation; its only purpose is to highlight the different problems that must be addressed. Implementers should therefore consider the following additional issues when implementing a Resource Processor service.

  • Changes could have been made to the Deployment Package objects when a Resource Processor's bundle was updated or has been offline for some time, which can happen when the uninstallForced method has been used. The Deployment Admin service can provide sufficient information to verify its repository to the information maintained in the Resource Processor service.

  • A Resource Processor service should have a strategy for transactions that can handle crash recovery. For example, in the previous code the list of createdWires and toBeDeletedWires should have been logged. Logging these lists would have allowed full crash recovery.

  • Better file formats should be considered. The Properties class is too restrictive because it can only have a single wire per Producer object. The Properties class was only chosen for its convenience.

  • Multi-threading issues may exist with the cancel method.

114.11 Events

The Deployment Admin service must publish several generic events to the Event Admin service in the course of a deployment operation. The purpose of these events is to allow, for example, a user interface to display the progress of a deployment operation to the user.

The topics to which Deployment Admin publishes events are:

The INSTALL, UNINSTALL and COMPLETE events have the following property:

The COMPLETE event additionally has the following property:

  • successful - (Boolean) Whether the deployment operation was successful or not.

114.12 Threading

The Deployment Admin service must be a singleton and must only process a single session at a time. When a client requests a new session with an install or uninstall operation, it must block that call until the earlier session is completed. The Deployment Admin service must throw a Deployment Exception when the session cannot be created after an appropriate time-out period. Resource Processor services can thus assume that all calls from begin to commit or rollback methods are called from the same thread.

Special care should be taken with the cancel method that is usually called from another thread.

114.13 Security

114.13.1 Deployment Admin Permission

The Deployment Admin Permission is needed to access the methods of the Deployment Admin service. The target for a Deployment Admin Permission is the same Filter string as for an Admin Permission, see Admin Permission of OSGi Core Release 7.

The actions are:

114.13.2 Deployment Customizer Permission

The DeploymentCustomizerPermission is used by customizer bundles. The target is the same as the target of Admin Permission: a filter that selects bundles. It has the following action:

  • PRIVATEAREA - Permits the use of the private area of the target bundles.

114.13.3 Permissions During an Install Session

Unprotected, Resource Processor services can unwittingly disrupt the device by processing incorrect or malicious resources in a Deployment Package. In order to protect the device, Resource Processor service's capabilities must be limited by the permissions granted to the union of the permissions of the Deployment Package's signers. This union is called the security scope. Given a signer, its security scope can be obtained from the Conditional Permission Admin Service Specification.

The Deployment Admin service must execute all Resource Processor service calls inside a doPrivileged block. This privileged block must use an AccessControlContext object that limits the permissions to the security scope. Therefore, a Resource Processor service must assume that it is always running inside the correct security scope. A Resource Processor can, of course, use its own security scope by doing a local doPrivileged block.

Bundle life cycle operations (install, uninstall, update) must be performed with the permissions granted to the Deployment Admin service implementation, they should not be further scoped because this could make it impossible to install unsigned Deployment Packages.

114.13.4 Contained Bundle Permissions

Bundles can be signed independently from the vehicle that deployed them. As a consequence, a bundle can be granted more permissions than its parent Deployment Package.

114.13.5 Service Registry Security

114.13.5.1 Deployment Admin Service

The Deployment Admin service is likely to require All Permission. This requirement is caused by the plugin model. Any permission required by any of the Resource Processor services must be granted to the Deployment Admin service as well. This set is large and difficult to define. The following list, however, shows the minimum permissions required if the permissions for the Resource Processor service permissions are ignored.

ServicePermission    ..DeploymentAdmin      REGISTER
ServicePermission    ..ResourceProcessor    GET
PackagePermission    ..deployment           EXPORTONLY

114.13.5.2 Resource Processor

ServicePermission    ..DeploymentAdmin      GET
ServicePermission    ..ResourceProcessor    REGISTER
PackagePermission    ..deployment           IMPORT

114.13.5.3 Client

ServicePermission    ..DeploymentAdmin      GET
PackagePermission    ..deployment           IMPORT

114.14 org.osgi.service.deploymentadmin

Version 1.1

Deployment Admin Package Version 1.1.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.deploymentadmin; version="[1.1,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.deploymentadmin; version="[1.1,1.2)"

114.14.1 Summary

114.14.2 public interface BundleInfo

Represents a bundle in the array given back by the DeploymentPackage.getBundleInfos() method.

114.14.2.1 public String getSymbolicName()

Returns the Bundle Symbolic Name of the represented bundle.

the Bundle Symbolic Name

114.14.2.2 public Version getVersion()

Returns the version of the represented bundle.

the version of the represented bundle

114.14.3 public interface DeploymentAdmin

This is the interface of the Deployment Admin service.

The OSGi Service Platform provides mechanisms to manage the life cycle of bundles, configuration objects, permission objects, etc. but the overall consistency of the runtime configuration is the responsibility of the management agent. In other words, the management agent decides to install, update, or uninstall bundles, create or delete configuration or permission objects, as well as manage other resource types, etc.

The Deployment Admin service standardizes the access to some of the responsibilities of the management agent. The service provides functionality to manage Deployment Packages (see DeploymentPackage). A Deployment Package groups resources as a unit of management. A Deployment Package is something that can be installed, updated, and uninstalled as a unit.

The Deployment Admin functionality is exposed as a standard OSGi service with no mandatory service parameters.

114.14.3.1 public boolean cancel()

This method cancels the currently active deployment session. This method addresses the need to cancel the processing of excessively long running, or resource consuming install, update or uninstall operations.

true if there was an active session and it was successfully canceled.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "cancel") permission.

DeploymentAdminPermission

114.14.3.2 public DeploymentPackage getDeploymentPackage(String symbName)

the symbolic name of the Deployment Package to be retrieved. It mustn't be null.

Gets the currently installed DeploymentPackage instance which has the given symbolic name.

During an installation of an existing package (update) or during an uninstallation, the target Deployment Package must remain the return value until the installation (uninstallation) process is completed, after which the source (or null in case of uninstall) is the return value.

The DeploymentPackage for the given symbolic name. If there is no Deployment Package with that symbolic name currently installed, null is returned.

IllegalArgumentException– if the given symbName is null

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "list") permission.

DeploymentPackage, DeploymentAdminPermission

114.14.3.3 public DeploymentPackage getDeploymentPackage(Bundle bundle)

the bundle whose owner is queried

Gives back the installed DeploymentPackage that owns the bundle. Deployment Packages own their bundles by their Bundle Symbolic Name. It means that if a bundle belongs to an installed Deployment Packages (and at most to one) the Deployment Admin assigns the bundle to its owner Deployment Package by the Symbolic Name of the bundle.

the Deployment Package Object that owns the bundle or null if the bundle doesn't belong to any Deployment Packages (standalone bundles)

IllegalArgumentException– if the given bundle is null

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "list") permission.

DeploymentPackage, DeploymentAdminPermission

114.14.3.4 public DeploymentPackage installDeploymentPackage(InputStream in) throws DeploymentException

the input stream the Deployment Package can be read from. It mustn't be null.

Installs a Deployment Package from an input stream. If a version of that Deployment Package is already installed and the versions are different, the installed version is updated with this new version even if it is older (downgrade). If the two versions are the same, then this method simply returns with the old (target) Deployment Package without any action.

A DeploymentPackage object representing the newly installed/updated Deployment Package. It is never null.

IllegalArgumentException– if the got InputStream parameter is null

DeploymentException– if the installation was not successful. For detailed error code description see DeploymentException.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "install") permission.

DeploymentAdminPermission, DeploymentPackage, DeploymentPackage

114.14.3.5 public DeploymentPackage[] listDeploymentPackages()

Lists the Deployment Packages currently installed on the platform.

DeploymentAdminPermission("<filter>", "list") is needed for this operation to the effect that only those packages are listed in the array to which the caller has appropriate DeploymentAdminPermission. It has the consequence that the method never throws SecurityException only doesn't put certain Deployment Packages into the array.

During an installation of an existing package (update) or during an uninstallation, the target must remain in this list until the installation (uninstallation) process is completed, after which the source (or null in case of uninstall) replaces the target.

the array of DeploymentPackage objects representing all the installed Deployment Packages. The return value cannot be null. In case of missing permissions it may give back an empty array.

DeploymentPackage, DeploymentAdminPermission

114.14.4 public final class DeploymentAdminPermission
extends Permission

DeploymentAdminPermission controls access to the Deployment Admin service.

The permission uses a filter string formatted similarly to the org.osgi.framework.Filter. The filter determines the target of the permission. The DeploymentAdminPermission uses the name and the signer filter attributes only. The value of the signer attribute is matched against the signer chain (represented with its semicolon separated Distinguished Name chain) of the Deployment Package, and the value of the name attribute is matched against the value of the "DeploymentPackage-Name" manifest header of the Deployment Package. Example:

  • (signer=cn = Bugs Bunny, o = ACME, c = US)

  • (name=org.osgi.ExampleApp)

Wildcards also can be used:

 (signer=cn=*,o=ACME,c=*)

"cn" and "c" may have an arbitrary value

 (signer=*, o=ACME, c=US)

Only the value of "o" and "c" are significant

 (signer=* ; ou=S & V, o=Tweety Inc., c=US)

The first element of the certificate chain is not important, only the second (the Distinguished Name of the root certificate)

 (signer=- ; *, o=Tweety Inc., c=US)

The same as the previous but '-' represents zero or more certificates, whereas the asterisk only represents a single certificate

 (name=*)

The name of the Deployment Package doesn't matter

 (name=org.osgi.*)

The name has to begin with "org.osgi."

The following actions are allowed:

list

A holder of this permission can access the inventory information of the deployment packages selected by the <filter> string. The filter selects the deployment packages on which the holder of the permission can acquire detailed inventory information. See DeploymentAdmin.getDeploymentPackage(Bundle), DeploymentAdmin.getDeploymentPackage(String) and DeploymentAdmin.listDeploymentPackages.

install

A holder of this permission can install/update deployment packages if the deployment package satisfies the <filter> string. See DeploymentAdmin.installDeploymentPackage.

uninstall

A holder of this permission can uninstall deployment packages if the deployment package satisfies the <filter> string. See DeploymentPackage.uninstall().

uninstall_forced

A holder of this permission can forcefully uninstall deployment packages if the deployment package satisfies the <filter> string. See DeploymentPackage.uninstallForced().

cancel

A holder of this permission can cancel an active deployment action. This action being canceled could correspond to the install, update or uninstall of a deployment package that satisfies the <filter> string. See DeploymentAdmin.cancel()

metadata

A holder of this permission is able to retrieve metadata information about a Deployment Package (e.g. is able to ask its manifest headers). See org.osgi.service.deploymentadmin.DeploymentPackage.getBundle(String), org.osgi.service.deploymentadmin.DeploymentPackage.getBundleInfos(), org.osgi.service.deploymentadmin.DeploymentPackage.getHeader(String), org.osgi.service.deploymentadmin.DeploymentPackage.getResourceHeader(String, String), org.osgi.service.deploymentadmin.DeploymentPackage.getResourceProcessor(String), org.osgi.service.deploymentadmin.DeploymentPackage.getResources()

The actions string is converted to lower case before processing.

114.14.4.1 public static final String CANCEL = "cancel"

Constant String to the "cancel" action.

DeploymentAdmin.cancel()

114.14.4.2 public static final String INSTALL = "install"

Constant String to the "install" action.

DeploymentAdmin.installDeploymentPackage(InputStream)

114.14.4.3 public static final String LIST = "list"

Constant String to the "list" action.

DeploymentAdmin.listDeploymentPackages(), DeploymentAdmin.getDeploymentPackage(String), DeploymentAdmin.getDeploymentPackage(Bundle)

114.14.4.5 public static final String UNINSTALL = "uninstall"

Constant String to the "uninstall" action.

DeploymentPackage.uninstall()

114.14.4.6 public static final String UNINSTALL_FORCED = "uninstall_forced"

Constant String to the "uninstall_forced" action.

DeploymentPackage.uninstallForced()

114.14.4.7 public DeploymentAdminPermission(String name, String actions)

filter string, must not be null.

action string, must not be null. "*" means all the possible actions.

Creates a new DeploymentAdminPermission object for the given name and action.

The name parameter identifies the target deployment package the permission relates to. The actions parameter contains the comma separated list of allowed actions.

IllegalArgumentException– if the filter is invalid, the list of actions contains unknown operations or one of the parameters is null

114.14.4.8 public boolean equals(Object obj)

The reference object with which to compare.

Checks two DeploymentAdminPermission objects for equality. Two permission objects are equal if:

  • their target filters are semantically equal and

  • their actions are the same

true if the two objects are equal.

java.lang.Object.equals(java.lang.Object)

114.14.4.9 public String getActions()

Returns the String representation of the action list.

The method always gives back the actions in the following (alphabetical) order: cancel, install, list, metadata, uninstall, uninstall_forced

Action list of this permission instance. This is a comma-separated list that reflects the action parameter of the constructor.

java.security.Permission.getActions()

114.14.4.10 public int hashCode()

Returns hash code for this permission object.

Hash code for this permission object.

java.lang.Object.hashCode()

114.14.4.11 public boolean implies(Permission permission)

Permission to check.

Checks if this DeploymentAdminPermission would imply the parameter permission.

Precondition of the implication is that the action set of this permission is the superset of the action set of the other permission. Further rules of implication are determined by the org.osgi.framework.Filter rules and the "OSGi Service Platform, Core Specification Release 4, Chapter Certificate Matching".

The allowed attributes are: name (the symbolic name of the deployment package) and signer (the signer of the deployment package). In both cases wildcards can be used.

Examples:

  1. DeploymentAdminPermission("(name=org.osgi.ExampleApp)", "list")
  2. DeploymentAdminPermission("(name=org.osgi.ExampleApp)", "list, install")
  3. DeploymentAdminPermission("(name=org.osgi.*)", "list")
  4. DeploymentAdminPermission("(signer=*, o=ACME, c=US)", "list")
  5. DeploymentAdminPermission("(signer=cn=Bugs Bunny, o=ACME, c=US)", "list")

  
  1. implies 1.
  2. implies 1.
  1. doesn't implies 2.
  3. implies 1.
  4. implies 5.

true if this DeploymentAdminPermission object implies the specified permission.

java.security.Permission.implies(java.security.Permission), org.osgi.framework.Filter

114.14.4.12 public PermissionCollection newPermissionCollection()

Returns a new PermissionCollection object for storing DeploymentAdminPermission objects.

The new PermissionCollection.

java.security.Permission.newPermissionCollection()

114.14.5 public class DeploymentException
extends Exception

Checked exception received when something fails during any deployment processes. A DeploymentException always contains an error code (one of the constants specified in this class), and may optionally contain the textual description of the error condition and a nested cause exception.

114.14.5.1 public static final int CODE_BAD_HEADER = 452

Syntax error in any manifest header.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.2 public static final int CODE_BUNDLE_NAME_ERROR = 457

Bundle symbolic name is not the same as defined by the deployment package manifest.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.3 public static final int CODE_BUNDLE_SHARING_VIOLATION = 460

Bundle with the same symbolic name already exists.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.4 public static final int CODE_CANCELLED = 401

DeploymentAdmin.installDeploymentPackage(InputStream), DeploymentPackage.uninstall() and DeploymentPackage.uninstallForced() methods can throw DeploymentException with this error code if the DeploymentAdmin.cancel() method is called from another thread.

114.14.5.5 public static final int CODE_COMMIT_ERROR = 462

Exception with this error code is thrown when one of the Resource Processors involved in the deployment session threw a ResourceProcessorException with the CODE_PREPARE error code.

DeploymentAdmin.installDeploymentPackage(InputStream) and DeploymentPackage.uninstall() methods throw exception with this error code.

114.14.5.6 public static final int CODE_FOREIGN_CUSTOMIZER = 458

Matched resource processor service is a customizer from another deployment package.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.7 public static final int CODE_MISSING_BUNDLE = 454

A bundle in the deployment package is marked as DeploymentPackage-Missing but there is no such bundle in the target deployment package.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.8 public static final int CODE_MISSING_FIXPACK_TARGET = 453

Fix pack version range doesn't fit to the version of the target deployment package or the target deployment package of the fix pack doesn't exist.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.9 public static final int CODE_MISSING_HEADER = 451

Missing mandatory manifest header.

DeploymentAdmin.installDeploymentPackage(InputStream) can throw exception with this error code.

114.14.5.10 public static final int CODE_MISSING_RESOURCE = 455

A resource in the source deployment package is marked as DeploymentPackage-Missing but there is no such resource in the target deployment package.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.11 public static final int CODE_NOT_A_JAR = 404

DeploymentAdmin.installDeploymentPackage(InputStream) methods can throw DeploymentException with this error code if the got InputStream is not a jar.

114.14.5.12 public static final int CODE_ORDER_ERROR = 450

Order of files in the deployment package is bad. The right order is the following:

  1. META-INF/MANIFEST.MF

  2. META-INF/*.SF, META-INF/*.DSA, META-INF/*.RS

  3. Localization files

  4. Bundles

  5. Resources

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.13 public static final int CODE_OTHER_ERROR = 463

Other error condition.

All Deployment Admin methods which throw DeploymentException can throw an exception with this error code if the error condition cannot be categorized.

114.14.5.14 public static final int CODE_PROCESSOR_NOT_FOUND = 464

The Resource Processor service with the given PID (see Resource-Processor manifest header) is not found.

DeploymentAdmin.installDeploymentPackage(InputStream), DeploymentPackage.uninstall() and DeploymentPackage.uninstallForced() throws exception with this error code.

114.14.5.15 public static final int CODE_RESOURCE_SHARING_VIOLATION = 461

An artifact of any resource already exists.

This exception is thrown when the called resource processor throws a ResourceProcessorException with the CODE_RESOURCE_SHARING_VIOLATION error code.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.16 public static final int CODE_SIGNING_ERROR = 456

Bad deployment package signing.

DeploymentAdmin.installDeploymentPackage(InputStream) throws exception with this error code.

114.14.5.17 public static final int CODE_TIMEOUT = 465

When a client requests a new session with an install or uninstall operation, it must block that call until the earlier session is completed. The Deployment Admin service must throw a Deployment Exception with this error code when the session can not be created after an appropriate time out period.

DeploymentAdmin.installDeploymentPackage(InputStream), DeploymentPackage.uninstall() and DeploymentPackage.uninstallForced() throws exception with this error code.

114.14.5.18 public DeploymentException(int code, String message, Throwable cause)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Message associated with the exception

the originating exception

Create an instance of the exception.

114.14.5.19 public DeploymentException(int code, String message)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Message associated with the exception

Create an instance of the exception. Cause exception is implicitly set to null.

114.14.5.20 public DeploymentException(int code)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Create an instance of the exception. Cause exception and message are implicitly set to null.

114.14.5.21 public Throwable getCause()

Returns the cause of this exception or null if no cause was set.

The cause of this exception or null if no cause was set.

114.14.5.22 public int getCode()

Returns the code.

114.14.5.23 public Throwable initCause(Throwable cause)

The cause of this exception.

Initializes the cause of this exception to the specified value.

This exception.

IllegalArgumentException– If the specified cause is this exception.

IllegalStateException– If the cause of this exception has already been set.

1.1

114.14.6 public interface DeploymentPackage

The DeploymentPackage object represents a deployment package (already installed or being currently processed). A Deployment Package groups resources as a unit of management. A deployment package is something that can be installed, updated, and uninstalled as a unit. A deployment package is a reified concept, like a bundle, in an OSGi Service Platform. It is not known by the OSGi Framework, but it is managed by the Deployment Admin service. A deployment package is a stream of resources (including bundles) which, once processed, will result in new artifacts (effects on the system) being added to the OSGi platform. These new artifacts can include installed Bundles, new configuration objects added to the Configuration Admin service, new Wire objects added to the Wire Admin service, or changed system properties, etc. All the changes caused by the processing of a deployment package are persistently associated with the deployment package, so that they can be appropriately cleaned up when the deployment package is uninstalled. There is a strict no overlap rule imposed on deployment packages. Two deployment packages are not allowed to create or manipulate the same artifact. Obviously, this means that a bundle cannot be in two different deployment packages. Any violation of this no overlap rule is considered an error and the install or update of the offending deployment package must be aborted.

The Deployment Admin service should do as much as possible to ensure transactionality. It means that if a deployment package installation, update or removal (uninstall) fails all the side effects caused by the process should be disappeared and the system should be in the state in which it was before the process.

If a deployment package is being updated the old version is visible through the DeploymentPackage interface until the update process ends. After the package is updated the updated version is visible and the old one is not accessible any more.

114.14.6.1 public static final String EVENT_DEPLOYMENTPACKAGE_CURRENTVERSION = "deploymentpackage.currentversion"

The currently installed version of the Deployment Package. The attribute is not present, if no version is installed:

  • in the INSTALL event, when an installDeploymentPackage was called and no earlier version is present

  • in the COMPLETE event after the _successfully_ completing an uninstallDeploymentPackage call

The value for this event must be a Version object.

1.1

114.14.6.2 public static final String EVENT_DEPLOYMENTPACKAGE_NAME = "deploymentpackage.name"

The name of the Deployment Package. This name is the same name as that specified in the DeploymentPackage-SymbolicName Manifest header.

1.1

114.14.6.3 public static final String EVENT_DEPLOYMENTPACKAGE_NEXTVERSION = "deploymentpackage.nextversion"

The version of DP after the successful completion of the install operation (used in INSTALL event only). The value for this event must be a Version object.

1.1

114.14.6.4 public static final String EVENT_DEPLOYMENTPACKAGE_READABLENAME = "deploymentpackage.readablename"

The human readable name of the DP localized to the default locale.

1.1

114.14.6.5 public boolean equals(Object other)

the reference object with which to compare.

Indicates whether some other object is "equal to" this one. Two deployment packages are equal if they have the same deployment package symbolic name and version.

true if this object is the same as the other argument; false otherwise.

114.14.6.6 public Bundle getBundle(String symbolicName)

the symbolic name of the requested bundle

Returns the bundle instance, which is part of this deployment package, that corresponds to the bundle's symbolic name passed in the symbolicName parameter. This method will return null for request for bundles that are not part of this deployment package.

As this instance is transient (i.e. a bundle can be removed at any time because of the dynamic nature of the OSGi platform), this method may also return null if the bundle is part of this deployment package, but is not currently defined to the framework.

The Bundle instance for a given bundle symbolic name.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

IllegalStateException– if the package is stale

114.14.6.7 public BundleInfo[] getBundleInfos()

Returns an array of BundleInfo objects representing the bundles specified in the manifest of this deployment package. Its size is equal to the number of the bundles in the deployment package.

array of BundleInfo objects

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

114.14.6.8 public String getDisplayName()

Returns the Deployment Package human readable name. This method returns the localized human readable name as set with the DeploymentPackage-Name manifest header using the default locale. If no header is set, this method will return null.

The human readable name of the deployment package or null if header is not set.

1.1

114.14.6.9 public String getHeader(String header)

the requested header

Returns the requested deployment package manifest header from the main section. Header names are case insensitive. If the header doesn't exist it returns null.

If the header is localized then the localized value is returned (see OSGi Service Platform, Mobile Specification Release 4 - Localization related chapters).

the value of the header or null if the header does not exist

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

114.14.6.10 public URL getIcon()

Returns a URL pointing to an image that represents the icon for this Deployment Package. The DeploymentPackage-Icon header can set an icon for the deployment package. This method returns an absolute URL that is defined by this header. The Deployment Admin service must provide this icon as a local resource. That is, the Deployment Admin must make a local copy of the specified icon. The returned URL's must point to a local resource.

An absolute URL to a local (device resident) image resource or null if not found

1.1

114.14.6.11 public String getName()

Returns the Deployment Package Symbolic Name of the package.

The name of the deployment package. It cannot be null.

114.14.6.12 public String getResourceHeader(String resource, String header)

the name of the resource (it is the same as the value of the "Name" attribute in the deployment package's manifest)

the requested header

Returns the requested deployment package manifest header from the name section determined by the resource parameter. Header names are case insensitive. If the resource or the header doesn't exist it returns null.

If the header is localized then the localized value is returned (see OSGi Service Platform, Mobile Specification Release 4 - Localization related chapters).

the value of the header or null if the resource or the header doesn't exist

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

114.14.6.13 public ServiceReference<ResourceProcessor> getResourceProcessor(String resource)

the name of the resource (it is the same as the value of the "Name" attribute in the deployment package's manifest)

At the time of deployment, resource processor service instances are located to resources contained in a deployment package.

This call returns a service reference to the corresponding service instance. If the resource is not part of the deployment package or this call is made during deployment, prior to the locating of the service to process a given resource, null will be returned. Services can be updated after a deployment package has been deployed. In this event, this call will return a reference to the updated service, not to the instance that was used at deployment time.

resource processor for the resource or null.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

IllegalStateException– if the package is stale

114.14.6.14 public String[] getResources()

Returns an array of strings representing the resources (including bundles) that are specified in the manifest of this deployment package. A string element of the array is the same as the value of the "Name" attribute in the manifest. The array contains the bundles as well.

E.g. if the "Name" section of the resource (or individual-section as the Manifest Specification calls it) in the manifest is the following

     Name: foo/readme.txt
     Resource-Processor: foo.rp

then the corresponding array element is the "foo/readme.txt" string.

The string array corresponding to resources. It cannot be null but its length can be zero.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission with "metadata" action

114.14.6.15 public Version getVersion()

Returns the version of the deployment package.

version of the deployment package. It cannot be null.

114.14.6.16 public int hashCode()

Returns a hash code value for the object.

a hash code value for this object

114.14.6.17 public boolean isStale()

Gives back the state of the deployment package whether it is stale or not). After uninstall of a deployment package it becomes stale. Any active method calls to a stale deployment package raise IllegalStateException. Active methods are the following:

true if the deployment package is stale. false otherwise

uninstall(), uninstallForced()

114.14.6.18 public void uninstall() throws DeploymentException

Uninstalls the deployment package. After uninstallation, the deployment package object becomes stale. This can be checked by using isStale(), which will return true when stale.

DeploymentException– if the deployment package could not be successfully uninstalled. For detailed error code description see DeploymentException.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "uninstall") permission.

IllegalStateException– if the package is stale

114.14.6.19 public boolean uninstallForced() throws DeploymentException

This method is called to completely uninstall a deployment package, which couldn't be uninstalled using traditional means (uninstall()) due to exceptions. After uninstallation, the deployment package object becomes stale. This can be checked by using isStale(), which will return true when stale.

The method forces removal of the Deployment Package from the repository maintained by the Deployment Admin service. This method follows the same steps as uninstall(). However, any errors or the absence of Resource Processor services are ignored, they must not cause a roll back. These errors should be logged.

true if the operation was successful

DeploymentException– only DeploymentException.CODE_TIMEOUT and DeploymentException.CODE_CANCELLED can be thrown. For detailed error code description see DeploymentException.

SecurityException– if the caller doesn't have the appropriate DeploymentAdminPermission("<filter>", "uninstall_forced") permission.

IllegalStateException– if the package is stale

114.15 org.osgi.service.deploymentadmin.spi

Version 1.0

Deployment Admin SPI Package Version 1.0. The SPI is used by Resource Processors.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.deploymentadmin.spi; version="[1.0,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.deploymentadmin.spi; version="[1.0,1.1)"

114.15.1 Summary

  • DeploymentCustomizerPermission - The DeploymentCustomizerPermission permission gives the right to Resource Processors to access a bundle's (residing in a Deployment Package) private area.

  • DeploymentSession - The session interface represents a currently running deployment session (install/update/uninstall).

  • ResourceProcessor - ResourceProcessor interface is implemented by processors handling resource files in deployment packages.

  • ResourceProcessorException - Checked exception received when something fails during a call to a Resource Processor.

114.15.2 public class DeploymentCustomizerPermission
extends Permission

The DeploymentCustomizerPermission permission gives the right to Resource Processors to access a bundle's (residing in a Deployment Package) private area. The bundle and the Resource Processor (customizer) have to be in the same Deployment Package.

The Resource Processor that has this permission is allowed to access the bundle's private area by calling the DeploymentSession.getDataFile(Bundle) method during the session (see DeploymentSession). After the session ends the FilePermissions are withdrawn. The Resource Processor will have FilePermission with "read", "write" and "delete" actions for the returned java.io.File that represents the base directory of the persistent storage area and for its subdirectories.

The actions string is converted to lowercase before processing.

114.15.2.1 public static final String PRIVATEAREA = "privatearea"

Constant String to the "privatearea" action.

114.15.2.2 public DeploymentCustomizerPermission(String name, String actions)

Bundle Symbolic Name of the target bundle, must not be null.

action string (only the "privatearea" or "*" action is valid; "*" means all the possible actions), must not be null.

Creates a new DeploymentCustomizerPermission object for the given name and action.

The name parameter is a filter string. This filter has the same syntax as an OSGi filter but only the "name" attribute is allowed. The value of the attribute is a Bundle Symbolic Name that represents a bundle. The only allowed action is the "privatearea" action. E.g.

 Permission perm = new DeploymentCustomizerPermission(
     "(name=com.acme.bundle)", "privatearea");

The Resource Processor that has this permission is allowed to access the bundle's private area by calling the DeploymentSession.getDataFile(Bundle) method. The Resource Processor will have FilePermission with "read", "write" and "delete" actions for the returned java.io.File and its subdirectories during the deployment session.

IllegalArgumentException– if the filter is invalid, the list of actions contains unknown operations or one of the parameters is null

114.15.2.3 public boolean equals(Object obj)

the reference object with which to compare.

Checks two DeploymentCustomizerPermission objects for equality. Two permission objects are equal if:

  • their target filters are equal (semantically and not character by character) and

  • their actions are the same

true if the two objects are equal.

java.lang.Object.equals(java.lang.Object)

114.15.2.4 public String getActions()

Returns the String representation of the action list.

Action list of this permission instance. It is always "privatearea".

java.security.Permission.getActions()

114.15.2.5 public int hashCode()

Returns hash code for this permission object.

Hash code for this permission object.

java.lang.Object.hashCode()

114.15.2.6 public boolean implies(Permission permission)

Permission to check.

Checks if this DeploymentCustomizerPermission would imply the parameter permission. This permission implies another DeploymentCustomizerPermission permission if:

  • both of them has the "privatearea" action (other actions are not allowed) and

  • their filters (only name attribute is allowed in the filters) match similarly to DeploymentAdminPermission.

The value of the name attribute means Bundle Symbolic Name and not Deployment Package Symbolic Name here!

true if this DeploymentCustomizerPermission object implies the specified permission.

java.security.Permission.implies(java.security.Permission)

114.15.2.7 public PermissionCollection newPermissionCollection()

Returns a new PermissionCollection object for storing DeploymentCustomizerPermission objects.

The new PermissionCollection.

java.security.Permission.newPermissionCollection()

114.15.3 public interface DeploymentSession

The session interface represents a currently running deployment session (install/update/uninstall).

When a deployment package is installed the target package, when uninstalled the source package is an empty deployment package. The empty deployment package is a virtual entity it doesn't appear for the outside world. It is only visible on the DeploymentSession interface used by Resource Processors. Although the empty package is only visible for Resource Processors it has the following characteristics:

114.15.3.1 public File getDataFile(Bundle bundle)

the bundle the private area belongs to

Returns the private data area of the specified bundle. The bundle must be part of either the source or the target deployment packages. The permission set the caller resource processor needs to manipulate the private area of the bundle is set by the Deployment Admin on the fly when this method is called. The permissions remain available during the deployment action only.

The bundle and the caller Resource Processor have to be in the same Deployment Package.

file representing the private area of the bundle. It cannot be null.

SecurityException– if the caller doesn't have the appropriate DeploymentCustomizerPermission("<filter>", "privatearea") permission.

DeploymentPackage, DeploymentCustomizerPermission

114.15.3.2 public DeploymentPackage getSourceDeploymentPackage()

If the deployment action is an install or an update, this call returns the DeploymentPackage instance that corresponds to the deployment package being streamed in for this session. If the deployment action is an uninstall, this call returns the empty deployment package (see DeploymentPackage).

the source deployment package

DeploymentPackage

114.15.3.3 public DeploymentPackage getTargetDeploymentPackage()

If the deployment action is an update or an uninstall, this call returns the DeploymentPackage instance for the installed deployment package. If the deployment action is an install, this call returns the empty deployment package (see DeploymentPackage).

the target deployment package

DeploymentPackage

114.15.4 public interface ResourceProcessor

ResourceProcessor interface is implemented by processors handling resource files in deployment packages. Resource Processors expose their services as standard OSGi services. Bundles exporting the service may arrive in the deployment package (customizers) or may be preregistered (they are installed previously). Resource processors has to define the service.pid standard OSGi service property which should be a unique string.

The order of the method calls on a particular Resource Processor in case of install/update session is the following:

  1. begin(DeploymentSession)

  2. process(String, InputStream) calls till there are resources to process or rollback() and the further steps are ignored

  3. dropped(String) calls till there are resources to drop

  4. prepare()

  5. commit() or rollback()

The order of the method calls on a particular Resource Processor in case of uninstall session is the following:

114.15.4.1 public void begin(DeploymentSession session)

object that represents the current session to the resource processor

Called when the Deployment Admin starts a new operation on the given deployment package, and the resource processor is associated a resource within the package. Only one deployment package can be processed at a time.

DeploymentSession

114.15.4.2 public void cancel()

Processing of a resource passed to the resource processor may take long. The cancel() method notifies the resource processor that it should interrupt the processing of the current resource. This method is called by the DeploymentAdmin implementation after the DeploymentAdmin.cancel() method is called.

114.15.4.3 public void commit()

Called when the processing of the current deployment package is finished. This method is called if the processing of the current deployment package was successful, and the changes must be made permanent.

114.15.4.4 public void dropAllResources() throws ResourceProcessorException

This method is called during an "uninstall" deployment session. This method will be called on all resource processors that are associated with resources in the deployment package being uninstalled. This provides an opportunity for the processor to cleanup any memory and persistent data being maintained for the deployment package.

ResourceProcessorException– if all resources could not be dropped. Only the ResourceProcessorException.CODE_OTHER_ERROR is allowed.

114.15.4.5 public void dropped(String resource) throws ResourceProcessorException

the name of the resource to drop (it is the same as the value of the "Name" attribute in the deployment package's manifest)

Called when a resource, associated with a particular resource processor, had belonged to an earlier version of a deployment package but is not present in the current version of the deployment package. This provides an opportunity for the processor to cleanup any memory and persistent data being maintained for the particular resource. This method will only be called during "update" deployment sessions.

ResourceProcessorException– if the resource is not allowed to be dropped. Only the ResourceProcessorException.CODE_OTHER_ERROR error code is allowed

114.15.4.6 public void prepare() throws ResourceProcessorException

This method is called on the Resource Processor immediately before calling the commit method. The Resource Processor has to check whether it is able to commit the operations since the last begin method call. If it determines that it is not able to commit the changes, it has to raise a ResourceProcessorException with the ResourceProcessorException.CODE_PREPARE error code.

ResourceProcessorException– if the resource processor is able to determine it is not able to commit. Only the ResourceProcessorException.CODE_PREPARE error code is allowed.

114.15.4.7 public void process(String name, InputStream stream) throws ResourceProcessorException

The name of the resource relative to the deployment package root directory.

The stream for the resource.

Called when a resource is encountered in the deployment package for which this resource processor has been selected to handle the processing of that resource.

ResourceProcessorException– if the resource cannot be processed. Only ResourceProcessorException.CODE_RESOURCE_SHARING_VIOLATION and ResourceProcessorException.CODE_OTHER_ERROR error codes are allowed.

114.15.4.8 public void rollback()

Called when the processing of the current deployment package is finished. This method is called if the processing of the current deployment package was unsuccessful, and the changes made during the processing of the deployment package should be removed.

114.15.5 public class ResourceProcessorException
extends Exception

Checked exception received when something fails during a call to a Resource Processor. A ResourceProcessorException always contains an error code (one of the constants specified in this class), and may optionally contain the textual description of the error condition and a nested cause exception.

114.15.5.1 public static final int CODE_OTHER_ERROR = 463

Other error condition.

All Resource Processor methods which throw ResourceProcessorException is allowed throw an exception with this error code if the error condition cannot be categorized.

114.15.5.2 public static final int CODE_PREPARE = 1

Resource Processors are allowed to raise an exception with this error code to indicate that the processor is not able to commit the operations it made since the last call of ResourceProcessor.begin(DeploymentSession) method.

Only the ResourceProcessor.prepare() method is allowed to throw exception with this error code.

114.15.5.3 public static final int CODE_RESOURCE_SHARING_VIOLATION = 461

An artifact of any resource already exists.

Only the ResourceProcessor.process(String, InputStream) method is allowed to throw exception with this error code.

114.15.5.4 public ResourceProcessorException(int code, String message, Throwable cause)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Message associated with the exception

the originating exception

Create an instance of the exception.

114.15.5.5 public ResourceProcessorException(int code, String message)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Message associated with the exception

Create an instance of the exception. Cause exception is implicitly set to null.

114.15.5.6 public ResourceProcessorException(int code)

The error code of the failure. Code should be one of the predefined integer values (CODE_X).

Create an instance of the exception. Cause exception and message are implicitly set to null.

114.15.5.7 public Throwable getCause()

Returns the cause of this exception or null if no cause was set.

The cause of this exception or null if no cause was set.

114.15.5.8 public int getCode()

Returns the code.

114.15.5.9 public Throwable initCause(Throwable cause)

The cause of this exception.

Initializes the cause of this exception to the specified value.

This exception.

IllegalArgumentException– If the specified cause is this exception.

IllegalStateException– If the cause of this exception has already been set.

1.0.1

114.16 References