Osgi Core-7 0 0 PDF
Osgi Core-7 0 0 PDF
Osgi Core-7 0 0 PDF
OSGi Core
Release 7
April 2018
Copyright © OSGi Alliance (2000, 2018).
All Rights Reserved.
OSGi Specification License, Version 2.0
License Grant
OSGi Alliance ("OSGi") hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited li-
cense (without the right to sublicense), under OSGi's applicable intellectual property rights to view, download,
and reproduce this OSGi Specification ("Specification") which follows this License Agreement ("Agreement"). You
are not authorized to create any derivative work of the Specification. However, to the extent that an implemen-
tation of the Specification would necessarily be a derivative work of the Specification, OSGi also grants you a
perpetual, non-exclusive, worldwide, fully paid-up, royalty free, limited license (without the right to sublicense)
under any applicable copyrights, to create and/or distribute an implementation of the Specification that: (i) ful-
ly implements the Specification including all its required interfaces and functionality; (ii) does not modify, sub-
set, superset or otherwise extend the OSGi Name Space, or include any public or protected packages, classes, Ja-
va interfaces, fields or methods within the OSGi Name Space other than those required and authorized by the
Specification. An implementation that does not satisfy limitations (i)-(ii) is not considered an implementation
of the Specification, does not receive the benefits of this license, and must not be described as an implementa-
tion of the Specification. An implementation of the Specification must not claim to be a compliant implementa-
tion of the Specification unless it passes the OSGi Compliance Tests for the Specification in accordance with OS-
Gi processes. "OSGi Name Space" shall mean the public class or interface declarations whose names begin with
"org.osgi" or any recognized successors or replacements thereof.
OSGi Participants (as such term is defined in the OSGi Intellectual Property Rights Policy) have made non-as-
sert and licensing commitments regarding patent claims necessary to implement the Specification, if any, un-
der the OSGi Intellectual Property Rights Policy which is available for examination on the OSGi public web site
(www.osgi.org).
General
The name and trademarks of OSGi or any other Authors may NOT be used in any manner, including advertis-
ing or publicity pertaining to the Specification or its contents without specific, written prior permission. Title to
copyright in the Specification will at all times remain with OSGi.
No other rights are granted by implication, estoppel or otherwise.
Trademarks
OSGi™ is a trademark, registered trademark, or service mark of the OSGi Alliance in the US and other countries.
Java is a trademark, registered trademark, or service mark of Oracle Corporation in the US and other countries.
All other trademarks, registered trademarks, or service marks used in this document are the property of their re-
spective owners and are hereby recognized.
Feedback
This specification can be downloaded from the OSGi Alliance web site:
https://www.osgi.org
Comments about this specification can be raised at:
https://osgi.org/bugzilla/
Table of Contents
1 Introduction 9
1.1 OSGi Framework Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 Reader Level. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3 Conventions and Terms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4 Version Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.5 References. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.6 Changes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2 Security Layer 19
2.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 Security Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.3 Digitally Signed JAR Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4 Permissions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5 References. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.6 Changes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3 Module Layer 33
3.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2 Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3 Dependencies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.4 Execution Environment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.5 Class Loading Architecture. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.6 Resolving Metadata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.7 Constraint Solving. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.8 Resolving Process. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.9 Runtime Class Loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.10 Loading Native Code Libraries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.11 Localization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.12 Bundle Validity. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.13 Requiring Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.14 Fragment Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3.15 Extension Bundles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
3.16 Security. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.17 References. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.18 Changes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
1 Introduction
The OSGi™ Alliance was founded in March 1999. Its mission is to create open specifications for
the network delivery of managed services to local networks and devices. The OSGi organization is
the leading standard for next-generation Internet services to homes, cars, mobile phones, desktops,
small offices, and other environments.
The OSGi Core specification delivers an open, common architecture for service providers, develop-
ers, software vendors, gateway operators and equipment vendors to develop, deploy and manage ser-
vices in a coordinated fashion. It enables an entirely new category of smart devices due to its flexi-
ble and managed deployment of services. OSGi specifications target set-top boxes, service gateways,
cable modems, consumer electronics, PCs, industrial computers, cars, mobile phones, and more. De-
vices that implement the OSGi specifications will enable service providers like telcos, cable opera-
tors, utilities, and others to deliver differentiated and valuable services over their networks.
This is the sixth release of the OSGi Core specification developed by representatives from OSGi
member companies. The OSGi Core Release 7 mostly extends the existing APIs into new areas. The
few modifications to existing APIs are backward compatible so that applications for previous releas-
es should run unmodified on Release 7 Frameworks. The built-in version management mechanisms
allow bundles written for the new release to adapt to the old Framework implementations, if neces-
sary.
• Security Layer
• Module Layer
• Life Cycle Layer
• Service Layer
• Actual Services
Bundles Service
Security
Life cycle
Module
Execution Environment
Hardware/OS
The Security Layer is based on Java security but adds a number of constraints and fills in some of the
blanks that standard Java leaves open. It defines a secure packaging format as well as the runtime
interaction with the Java security layer. The Security Layer is described in Security Layer on page
19.
The Module Layer defines a modularization model for Java. It addresses some of the shortcomings
of Java's deployment model. The modularization layer has strict rules for sharing Java packages be-
tween bundles or hiding packages from other bundles. The Module Layer can be used without the
life cycle and Service Layer. The Life Cycle Layer provides an API to manage the bundles in the Mod-
ule Layer, while the Service Layer provides a communication model for the bundles. The Module
Layer is described in Module Layer on page 33.
The Life Cycle Layer provides a life cycle API to bundles. This API provides a runtime model for bun-
dles. It defines how bundles are started and stopped as well as how bundles are installed, updated
and uninstalled. Additionally, it provides a comprehensive event API to allow a management bun-
dle to control the operations of the OSGi framework. The Life Cycle Layer requires the Module Layer
but the Security Layer is optional. A more extensive description of the Life Cycle layer can be found
at Life Cycle Layer on page 99.
The Service Layer provides a dynamic, concise and consistent programming model for Java bun-
dle developers, simplifying the development and deployment of service bundles by de-coupling the
service's specification (Java interface) from its implementations. This model allows bundle develop-
ers to bind to services only using their interface specifications. The selection of a specific implemen-
tation, optimized for a specific need or from a specific vendor, can thus be deferred to run-time.
The framework uses the service layer to provide an extension mechanism, called hooks. Hooks are
services that are used by the framework to provide additional functionality.
A consistent programming model helps bundle developers cope with scalability issues in many dif-
ferent dimensions - critical because the Framework is intended to run on a variety of devices whose
differing hardware characteristics may affect many aspects of a service implementation. Consistent
interfaces insure that the software components can be mixed and matched and still result in stable
systems.
The Framework allows bundles to select an available implementation at run-time through the
Framework service registry. Bundles register new services, receive notifications about the state of
services, or look up existing services to adapt to the current capabilities of the device. This aspect
of the Framework makes an installed bundle extensible after deployment: new bundles can be in-
stalled for added features or existing bundles can be modified and updated without requiring the
system to be restarted.
The Service Layer is described in Service Layer on page 133.
The interactions between the layers is depicted in Figure 1.2.
register
unregister Service
get
unget
manage
start Life Cycle
stop
Bundle
Install
uninstall
class load Module
execute EE
• Application developers
• Framework and system service developers (system developers)
• Architects
The OSGi Specifications assume that the reader has at least one year of practical experience in writ-
ing Java programs. Experience with embedded systems and server environments is a plus. Applica-
tion developers must be aware that the OSGi environment is significantly more dynamic than tradi-
tional desktop or server environments.
System developers require a very deep understanding of Java. At least three years of Java coding ex-
perience in a system environment is recommended. A Framework implementation will use areas
of Java that are not normally encountered in traditional applications. Detailed understanding is re-
quired of class loaders, garbage collection, Java security, and Java native library loading.
Architects should focus on the introduction of each subject. This introduction contains a general
overview of the subject, the requirements that influenced its design, and a short description of its
operation as well as the entities that are used. The introductory sections require knowledge of Java
concepts like classes and interfaces, but should not require coding experience.
Most of these specifications are equally applicable to application developers and system developers.
When an example contains a line that must be broken into multiple lines, the « character is used.
Spaces must be ignored in this case. For example:
http://www.acme.com/sp/ «
file?abc=12
is equivalent to:
http://www.acme.com/sp/file?abc=12
The following terminals are pre defined and used throughout the specifications:
for whitespace>]
Whitespaces between terminals are ignored unless specifically noted. Any value that contains a
space, a comma, colon, semi-colon, equal sign or any other character that is part of a terminal in the
grammar must be quoted.
1.3.4 Diagrams
The diagrams in this document illustrate the specification and are not normative. Their purpose is
to provide a high-level overview on a single page. The following paragraphs describe the symbols
and conventions used in these diagrams.
Classes or interfaces are depicted as rectangles, as in Figure 1.3. Interfaces are indicated with the
qualifier <<interface>> as the first line. The name of the class/interface is indicated in bold when it
is part of the specification. Implementation classes are sometimes shown to demonstrate a possible
implementation. Implementation class names are shown in plain text. In certain cases class names
are abbreviated. This is indicated by ending the abbreviation with a full stop.
If an interface or class is used as a service object, it will have a black triangle in the bottom right cor-
ner.
<<interface>>
Permission
Admin
Service are crucial interaction elements and they can occur many times in diagrams describing ser-
vices. Therefore, an alternative service symbol is the triangle. Triangles can be connected in differ-
ent ways, representing different meanings:
• Point - Connections to the point of a triangle indicate the registration. This makes the point of the
triangle point to the object that receives the method calls from the service users.
• Straight Side - Connections to the straight side indicate service clients. Clients call the methods of
the service.
• Angled Side - The angled side is reserved for service listeners.
listen
Service
Listener
Inheritance (the extends or implements keyword in Java class definitions) is indicated with an ar-
row. Figure 1.6 shows that the AdminPermission class implements or extends the Permission class.
<<class>> <<class>>
Admin Permission
Permission
Relations are depicted with a line. The cardinality of the relation is given explicitly when relevant.
Figure 1.7 shows that each (1) BundleContext object is related to 0 or more BundleListener objects,
and that each BundleListener object is related to a single BundleContext object. Relations usually
have some description associated with them. This description should be read from left to right and
top to bottom, and includes the classes on both sides. For example: "A BundleContext object delivers
bundle events to zero or more BundleListener objects."
<<interface>> <<interface>>
1 delivers bundle events 0..*
Bundle Bundle
Context Listener
Associations are depicted with a dashed line. Associations are between classes, and an association
can be placed on a relation. For example, "every ServiceRegistration object has an associated Ser-
viceReference object." This association does not have to be a hard relationship, but could be derived
in some way.
When a relationship is qualified by a name or an object, it is indicated by drawing a dotted line per-
pendicular to the relation and connecting this line to a class box or a description. Figure 1.8 shows
that the relationship between a UserAdmin class and a Role class is qualified by a name. Such an as-
sociation is usually implemented with a Dictionary or Map object.
name
Bundles are entities that are visible in normal application programming. For example, when a bun-
dle is stopped, all its services will be unregistered. Therefore, the classes/interfaces that are grouped
in bundles are shown on a grey rectangle as is shown in Figure 1.9.
0..n
name
1
Implementation
UserAdminImpl RoleImpl
bundle
• must - An absolute requirement. Both the Framework implementation and bundles have obliga-
tions that are required to be fulfilled to conform to this specification.
• should - Recommended. It is strongly recommended to follow the description, but reasons may
exist to deviate from this recommendation.
• may or can - Optional. Implementations must still be interoperable when these items are not im-
plemented.
currency point-of-view, this means that the actions described in lower numbered items happens-be-
fore the actions described in higher numbered items.
A compliant framework implementation must implement all of the specifications in this document
except as outlined below.
• 50 Conditional Permission Admin Service Specification and 51 Permission Admin Service Specification
are mandatory only if 2 Security Layer is supported and a Security Manager is installed.
• 52 URL Handlers Service Specification is mandatory if the framework implementation system bun-
dle exports the org.osgi.service.url package.
1.5 References
[1] Java Language Specification
http://docs.oracle.com/javase/specs/
1.6 Changes
• Added Numbered Lists to specify the happens-before relationship between items in numbered lists.
• Added org.osgi.annotation.bundle.
• Resolver Service Specification moved to Core from OSGi Compendium, Chapter 136.
2 Security Layer
Version 1.9
2.1 Introduction
The OSGi Security Layer is an optional layer that underlies the OSGi framework. The layer is based
on the Java security architecture. It provides the infrastructure to deploy and manage applications
that must run in fine-grained controlled environments.
2.1.1 Essentials
• Fine-grained - The control of applications running in an OSGi Framework must allow for detailed
control of those applications.
• Manageable - The security layer itself does not define an API to control the applications. The man-
agement of the security layer is left to the life cycle layer.
• Optional - The security layer is optional.
• By location
• By signer
At higher layers there are defined services that can manage the permissions that are associated with
the authenticated unit of code. These services are:
• Permission Admin service - Manages the permission based on full location strings.
• Conditional Permission Admin service - Manages the permissions based on a comprehensive condi-
tional model, where the conditions can test for location or signer.
For signing, this requires the JAR files to be signed; this is described in Digitally Signed JAR Files on
page 20.
In an OSGi Framework, the principals that signed a JAR become associated with that JAR. This asso-
ciation is then used to:
For example, an Operator can grant the ACME company the right to use networking on their de-
vices. The ACME company can then use networking in every bundle they digitally sign and deploy
on the Operator's device. Also, a specific bundle can be granted permission to only manage the life
cycle of bundles that are signed by the ACME company.
Signing provides a powerful delegation model. It allows an Operator to grant a restricted set of per-
missions to a company, after which the company can create JARs that can use those permissions,
without requiring any intervention of, or communication with, the Operator for each particular
JAR. This delegation model is shown graphically in Figure 2.1.
Figure 2.1 Delegation model
provides
Developer Enterprise
installs
OSGi
uses grants
Framework
permissions
Employee Operator
Digital signing is based on public key cryptography. Public key cryptography uses a system where
there are two mathematically related keys: a public and a private key. The public key is shared with
the world and can be dispersed freely, usually in the form of a certificate. The private key must be
kept a secret.
Messages signed with the private key can only be verified correctly with the public key. This can be
used to authenticate the signer of a message (assuming the public key is trusted, this is discussed in
Certificates on page 23).
The digital signing process used is based on Java JAR signing. The process of signing is repeated, re-
stricted and augmented here to improve the interoperability of OSGi bundles.
• A signature instruction resource that has a similar format like the Manifest. It must have a .SF ex-
tension. This file provides digests for the complete manifest file.
• A PKCS#7 resource that contains the digital signature of the signature instruction resource. See
[10] Public Key Cryptography Standard #7 for information about its format.
These JAR file signing resources must be placed in the META-INF directory. For signing, the META-
INF directory is special because files in there are not signed in the normal way. These signing re-
sources must come directly after the MANIFEST.MF file, and before any other resources in a JAR
stream. If this is not the case, then a Framework should not accept the signatures and must treat
the bundle as unsigned. This ordering is important because it allows the receiver of the JAR file
to stream the contents without buffering. All the security information is available before any re-
sources are loaded. This model is shown in Figure 2.2.
The signature instruction resource contains digests of the Manifest resource, not the actual resource
data itself. A digest is a one way function that computes a value from the bytes of a resource in such
a way that it is very difficult to create a set of bytes that matches that digest value.
The JAR Manifest must therefore contain one or more digests of the actual resources. These digests
must be placed in their name section of the manifest. The name of the digest header is constructed
with its algorithm followed by -Digest. An example is the SHA-256-Digest. It is recommended that
OSGi Framework implementations support the following digest algorithms.
• SHA-1 - Delivers a 160 bit hash. It is defined in [6] Secure Hash Standard.
• SHA-256 - Delivers a 256 bit hash. It is defined in [6] Secure Hash Standard.
The hash must be encoded with a Base 64 encoding. Base 64 encoding is defined in [7] RFC 1421 Pri-
vacy Enhancement for Internet Electronic Mail.
For example, a manifest could look like:
Manifest-Version: 1.0
Bundle-Name: DisplayManifest
↵
Name: x/A.class
SHA-256-Digest: 7CCToQk6yvRusxNl0uSwrv37UY/fdz6aHou29mbswsM=
↵
Name: x/B.class
SHA-256-Digest: C+0CG/cy13WD2sq8dRZm+dNWAHIjm4RQmUVeLLv7DVU=
↵
OSGi JARs must be signed by one or more signers that sign all resources except the ones in the
META-INF directory; the default behavior of the jarsigner tool. This is a restriction with respect to
standard Java JAR signing; there is no partial signing for an OSGi JAR. The OSGi specification only
supports fully signed bundles. The reason for this restriction is because partially signing can break
the protection of private packages. It also simplifies the security API because all code of a bundle is
using the same protection domain.
Signature files in nested JAR files (For example JARs on the Bundle-ClassPath) must be ignored.
These nested JAR files must share the same protection domain as their containing bundle. They
must be treated as if their resources were stored directly in the outer JAR.
Each signature is based on two resources. The first file is the signature instruction file; this file must
have a file name with an extension .SF. A signature file has the same syntax as the manifest, except
that it starts with Signature-Version: 1.0 instead of Manifest-Version: 1.0.
The only relevant part of the signature resource is the digest of the Manifest resource. The name of
the header must be the name algorithm (e.g. SHA-256) followed by -Digest-Manifest. For example:
Signature-Version: 1.0
SHA-256-Digest-Manifest: HmK7445BA7n5UYYI9xZKfSdMAPci44Jn7ZcmoyoiWoM=
The signature resource can contain name sections as well. However, these name sections should be
ignored.
If there are multiple signers, then their signature instruction resources can be identical if they use
the same digest algorithms. However, each signer must still have its own signature instruction file.
That is, it is not allowed to share the signature resource between signers.
The indirection of the signature instruction files digests is depicted in Figure 2.4 for two signers:
ACME and DAFFY.
signature
with private key
META-INF/
... other files certificates
ACME.RSA
ACME.SF
signature
MANIFEST.MF with private key
certificates
• Bundles do not support partially signed bundles. The manifest must contain name sections for
all resources but should not have entries for resources in the META-INF directory. Signed entries
in the META-INF directory must be verified. Sub directories of META-INF must be treated like
any other JAR directory.
• The name sections in the signature files are ignored. Only the Manifest digest is used.
For a complete bundle to be validly signed it is necessary that all signatures are valid. That is, if one
of the signatures is invalid, the whole bundle must be treated as unsigned.
• DSA - The Digital Signature Algorithm. This standard is defined in [8] DSA. This is a USA govern-
ment standard for Digital Signature Standard. The signature resource name must have an exten-
sion of .DSA.
• RSA - Rivest, Shamir and Adleman. A public key algorithm that is very popular. It is defined in [9]
RSA. The extension of the signature resource name must be .RSA.
The signature files for RSA and DSA are stored in a PKCS#7 format. This is a format that has a struc-
ture as defined in [10] Public Key Cryptography Standard #7. The PKCS#7 standard provides access to
the algorithm specific signing information as well as the certificate with the public key of the sign-
er. The verification algorithm uses the public key to verify that:
2.3.5 Certificates
A certificate is a general term for a signed document containing a name and public key information.
Such a certificate can take many forms but the OSGi JAR signing is based on the X.509 certificate for-
mat. It has been around for many years and is part of the OSI group of standards. X.509 is defined in
[2] X.509 Certificates.
An X.509 certificate contains the following elements:
• Subject Name - The subject name is a unique identifier for the object being certified. In the case of
a person this might include the name, nationality and e-mail address, the organization, and the
department within that organization. This identifier is a Distinguished Name, which is defined
in Distinguished Names on page 25.
• Issuer Name - The Issuer name is a Distinguished Name for the principal that signed this certifi-
cate.
• Certificate Extensions - A certificate can also include pictures, codification of fingerprints, passport
number, and other extensions.
• Public Key Information - A public key can be used with an encryption technique that requires its
private counterpart to decrypt, and vice versa. The public key can be shared freely, the private
key must be kept secret. The public key information specifies an algorithm identifier (such as
DSA or RSA) and the subject's public key.
• Validity - A Certificate can be valid for only a limited time.
• Certifying Authority Signature - The Certificate Authority signs the first elements and thereby adds
credibility to the certificate. The receiver of a certificate can check the signature against a set of
trusted certifying authorities. If the receiver trusts that certifying authority, it can trust the state-
ment that the certificate makes.
issuer DN
validity
extensions digest
public key
signature private key from other certificate
Certificates can be freely dispersed; they do not contain any secret information. Therefore, the
PKCS#7 resource contains the signing certificate. It cannot be trusted at face value because the cer-
tificate is carried in the bundle itself. A perpetrator can easily create its own certificate with any con-
tent. The receiver can only verify that the certificate was signed by the owner of the public key (the
issuer) and that it has not been tampered with. However, before the statement in the certificate can
be trusted, it is necessary to authenticate the certificate itself. It is therefore necessary to establish a
trust model.
One trust model, supported but not required by the OSGi specifications, is placing the signing cer-
tificate in a repository. Any certificate in this repository is treated as trusted by default. However,
placing all possible certificates in this repository does not scale well. In an open model, a device
would have to contain hundreds of thousands of certificates. The management of the certificates
could easily become overwhelming.
The solution is to sign a certificate by another certificate, and this process can be repeated several
times. This delegation process forms a chain of certificates. All certificates for this chain are carried in
the PKCS#7 file: if one of those certificates can be found in the trusted repository, the other depen-
dent ones can be trusted, on the condition that all the certificates are valid. This model scales very
well because only a few certificates of trusted signers need to be maintained. This is the model used
in web browsers, as depicted in Figure 2.6.
App
Cert
Signs
Thawte
Signing
This specification does not specify access to the trusted repository. It is implementation specific
how this repository is populated and maintained.
cn=Bug,o=ACME,c=US
1
* Root
C = Country c=US
FR US
1
* o=ACME
O == Obelix ACME
Organization
Organization
cn=Bugs
1
* Bugs
CN = Common
Name
The traversal of the namespace is reversed from the order in the DN, the first part specifies the least
significant but most specific part. That is, the order of the attribute assertions is significant. Two
DNs with the same attributes but different order are different DNs.
In the example, a node is searched in the root that has an attribute c (countryName) with a value
that is US. This node is searched for a child that has an attribute o (organizationName) with a value
of ACME. And the ACME node is searched for a child node with an attribute cn (commonName) that
has a value "Bugs Bunny".
The tree based model is the official definition of a DN from the X.500 standards. However, in prac-
tice today, many DNs contain attributes that have no relation to a tree. For example, many DNs con-
tain comments and copyrights in the ou (organizationalUnit) attribute.
The DN from an X.509 certificate is expressed in a binary structure defined by ASN.1 (a type lan-
guage defined by ISO). However, the Distinguished Name is often used in interaction with hu-
mans. Sometimes, users of a system have to acknowledge the use of a certificate or an employ-
ee of an Operator must grant permissions based on a Distinguished Name of a customer. It is
therefore paramount that the Distinguished Name has a good human readable string represen-
tation. The expressiveness of the ASN.1 type language makes this non-trivial. This specification
only uses DN strings as defined in [1] RFC 2253Lightweight Directory Access Protocol (v3): UTF-8
String Representation of Distinguished Names with a number of extensions that are specified by the
javax.security.auth.x500.X500Principal class in CANONICAL form.
However, the complexity of the encoding/decoding is caused by the use of rarely used types and fea-
tures (binary data, multi-valued RDNs, foreign alphabets, and attributes that have special matching
rules). These features must be supported by a compliant implementation but should be avoided by
users. In practice, these features are rarely used today.
The format of a string DN is as follows:
Spaces before and after the separators are ignored, spaces inside a value are significant but multiple
embedded spaces are collapsed into a single space. Wildcard asterisks ('*' \u002A) are not allowed
in a value part. The following characters must be escaped with a reverse solidus ('\' \u005C):
Reverse solidi ('\' \u005C) must already be escaped in Java strings, requiring 2 reverse solidi in Java
source code. For example:
The full Unicode character set is available and can be used in DNs. String objects must be normal-
ized and put in canonical form before being compared.
The names of attributes (attributes types as they are also called) are actually translated into an Ob-
ject IDentifier (OID). An OID is a dotted decimal number, like 2.5.4.3 for the cn (commonName) at-
tribute name. It is therefore not possible to use any attribute name because the implementation
must know the aliasing as well as the comparison rules. Therefore only the attributes that are listed
in the following table are allowed (in short or long form):
surName sn 2.5.4.4
countryName c 2.5.4.6
localityName l 2.5.4.7
stateOrProvinceName st 2.5.4.8
organizationName o 2.5.4.10
organizationalUnitName ou 2.5.4.11
title 2.5.4.12
givenName 2.5.4.42
initials 2.5.4.43
generationQualifier 2.5.4.44
dnQualifier 2.5.4.46
2.5.4.3=Bugs Bunny,organizationName=ACME,2.5.4.6=US
cn=Bugs Bunny,o=ACME,c=US
The attribute types officially define a matching rule, potentially allowing cases sensitive and case
insensitive. The attributes in the previous list all match case insensitive. Therefore, an OSGi DN
must not depend on case sensitivity.
The X.500 standard supports multi-valued RDNs, however, their use is not recommended. See [12]
Understanding and Deploying LDAP Directory Services for the rationale of this recommendation. Mul-
ti-valued RDNs separate their constituents with a plus sign ('+' \u002B). Their order is not signifi-
cant. For example:
cn=Bugs Bunny+dc=x.com+title=Manager,o=ACME,c=US
The most simple case is a single wildcard; it must match any DN. A wildcard can also replace the
first list of RDNs of a DN. The first RDNs are the least significant. Such lists of matched RDNs can be
empty.
For example, a DN with a wildcard that matches all nodes descendant from the ACME node in Figure
2.7 on page 25, looks like:
*, o=ACME, c=US
If a wildcard is used for a value of an RDN, the value must be exactly *. The wildcard must match
any value, and no substring matching must be done. For example:
cn=*,o=ACME,c=*
cn=Bugs Bunny,o=ACME,c=US
cn = Daffy Duck , o = ACME , c = US
cn=Road Runner, o=ACME, c=NL
But not:
o=ACME, c=NL
dc=acme.com, cn=Bugs Bunny, o=ACME, c=US
Both forms of wildcard usage can be combined in a single matching DN. For example, to match any
DN that is from the ACME company worldwide, use:
*, o=ACME, c=*
Matching of a DN takes place in the context of a certificate. This certificate is part of a certificate
chain, see Certificates on page 23. Each certificate has a Subject DN and an Issuer DN. The Issuer
DN is the Subject DN used to sign the first certificate of the chain. DN matching can therefore be ex-
tended to match the signer. The semicolon (';' \u003B) must be used to separate DNs in a chain.
The following example matches a certificate signed by Tweety Inc. in the US.
The wildcard matches zero or one certificates, however, sometimes it is necessary to match a longer
chain. The minus sign ('-' \u002D) represents zero or more certificates, whereas the asterisk only
represents a single certificate. For example, to match a certificate where the Tweety Inc. is in the cer-
tificate chain, use the following expression:
The previous example matched if the Tweety Inc. certificate was trusted, or was signed by a trusted
certificate. Certain certificates are trusted because they are known by the Framework, how they are
known is implementation-defined.
2.4 Permissions
The OSGi Framework uses Java permissions for securing bundles. Each bundle is associated with
a set of permissions. During runtime, the permissions are queried when a permission is requested
through the Security Manager. If a Framework uses postponed conditions, then it must install its
own security manager, otherwise it can use any Security Manager.
The management of the bundle's permissions is handled through Conditional Permission Admin,
Permission Admin, or another security agent.
• File Permission for the bundle persistent storage area, for the READ, WRITE, and DELETE actions.
• Property Permission with the READ action for org.osgi.framework.*.
• Admin Permission with the RESOURCE, METADATA , CLASS, and CONTEXT actions for the bundle
itself.
• Capability Permission REQUIRE for the osgi.ee namespace.
• Capability Permission REQUIRE for the osgi.native namespace.
• Package Permission IMPORT for java.*.
ServicePermission("(location=https://www.acme.com/*)",GET )
This provides a very powerful model because it allows operators to let a group of bundles closely
collaborate without requiring ad hoc namespaces for services, packages, and bundles. Using the
signer or location as the target for a permission, will allow the maintenance of the permission man-
agement to be significantly reduced. It is not necessary to configure for individual bundles: the sign-
er or location is effectively used as a grouping mechanism.
The filter can contain the following keys:
(id=256)
• location - The location of a bundle. Filter wildcards for Strings are supported, allowing the value
to specify a set of bundles. For example:
(location=https://www.acme.com/download/*)
• signer - A Distinguished Name chain. See Certificate Matching on page 27 for more informa-
tion how Distinguished Names are matched. Wildcards in a DN are not matched according to
the filter string rules, but according to the rules defined for a DN chain. The wildcard asterisk ('*'
\u002A) must be escaped with a reverse solidus ('\' \u005C) to avoid being interpreted as a filter
wildcard. For example:
(signer=\*,o=ACME,c=NL)
• name - The symbolic name of a bundle. Filter wildcards for Strings are supported allowing the
value to specify a set of bundles. A single symbolic name may also map to a set of bundles. For ex-
ample:
(name=com.acme.*)
The name parameter of the permission can also be a single wildcard asterisk ('*' \u002A). In that
case all bundles must match.
2.5 References
[1] RFC 2253Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
http://www.ietf.org/rfc/rfc2253.txt
[2] X.509 Certificates
http://www.ietf.org/rfc/rfc2459.txt
[3] Java Security Architecture
https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc.html
[4] Java Package Versioning Specification
https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/index.html
[5] Manifest Format
https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Manifest
[6] Secure Hash Standard
http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
[7] RFC 1421 Privacy Enhancement for Internet Electronic Mail
http://www.ietf.org/rfc/rfc1421.txt
[8] DSA
http://www.itl.nist.gov/fipspubs/fip186.htm
[9] RSA
http://www.ietf.org/rfc/rfc2313.txt which is superseded by http://www.ietf.org/rfc/rfc2437.txt
[10] Public Key Cryptography Standard #7
http://www.rsasecurity.com/rsalabs/node.asp?id=2129
[11] Unicode Normalization UAX # 15
http://www.unicode.org/reports/tr15/
[12] Understanding and Deploying LDAP Directory Services
ISBN 1-57870-070-1
2.6 Changes
• Updated references to current URLs.
• Removed MD5 and added SHA-256 digest algorithms.
• Added Package Permission IMPORT for java.* to the implied permissions. See Implied Permissions
on page 29.
3 Module Layer
Version 1.9
3.1 Introduction
The standard Java platform provides only limited support for packaging, deploying, and validating
Java-based applications and components. Because of this, many Java-based projects, such as JBoss
and NetBeans, have resorted to creating custom module-oriented layers with specialized class load-
ers for packaging, deploying, and validating applications and components. The OSGi Framework
provides a generic and standardized solution for Java modularization.
3.2 Bundles
The Framework defines a unit of modularization, called a bundle. A bundle is comprised of Java
classes and other resources, which together can provide functions to end users. Bundles can share
Java packages among an exporter bundle and an importer bundle in a well-defined way. In the OSGi
framework, bundles are the only entities for deploying Java-based applications.
A bundle is deployed as a Java ARchive (JAR) file. JAR files are used to store applications and their re-
sources in a standard ZIP-based file format. This format is defined by [9] Zip File Format. Bundles nor-
mally share the Java Archive extension of .jar. However, there is a special MIME type reserved for
OSGi bundles that can be used to distinguish bundles from normal JAR files. This MIME type is:
application/vnd.osgi.bundle
• Contains the resources necessary to provide some functionality. These resources may be class
files for the Java programming language, as well as other data such as HTML files, help files,
icons, and so on. A bundle JAR file can also embed additional JAR files that are available as re-
sources and classes. This is however not recursive.
• Contains a manifest file describing the contents of the JAR file and providing information about
the bundle. This file uses headers to specify information that the Framework needs to install cor-
rectly and activate a bundle. For example, it states dependencies on other resources, such as Java
packages, that must be available to the bundle before it can run.
• Can contain optional documentation in the OSGI-OPT directory of the JAR file or one of its sub-
directories. Any information in this directory is optional. For example, the OSGI-OPT directory is
useful to store the source code of a bundle. Management systems may remove this information
to save storage space in the OSGi framework.
• Can be a multi-release JAR. See Multi-release JAR on page 41.
Once a bundle is resolved, its functionality is provided to other bundles installed in the OSGi frame-
work.
• Process the main section of the manifest. Individual sections of the manifest are only used dur-
ing bundle signature verification.
• Ignore unrecognized manifest headers. The bundle developer can define additional manifest
headers as needed.
• Ignore unknown attributes and directives.
All specified manifest headers are listed in the following sections. All headers are optional, unless
specifically indicated.
See [26] Maven POM Reference, Developers for more information. Tools can use the information in this
header for POM generation.
• size - (integer) Specifies the size of the icon in pixels horizontal. It is recommended to always in-
clude a 64x64 icon.
The URLs are interpreted as relative to the bundle. That is, if a URL with a scheme is provided, then
this is taken as an absolute URL. Otherwise, the path points to an entry in the JAR file, taking any at-
tached fragments into account. Implementations that want to use this header should at least sup-
port the Portable Network Graphics (PNG) format, see [18] Portable Network Graphics (PNG) Specifica-
tion (Second Edition).
• license-identifier - Provides a globally unique identifier for this license, preferably world wide,
but it should at least be unique with respect to the other clauses. The magic identifier <<EXTER-
NAL>> is used to indicate that this artifact does not specify any license information but that li-
censing information is provided in some other way. This is also the default value of this header.
This identifier should be one of the identifiers defined by [25] Software Package Data Exchange
(SPDX) License List. Clients of this bundle can assume that licenses with the same identifier refer
to the same license. This can for example be used to minimize the click through licenses.
Alternatively, the identifier can be the canonical URL of the license, it must not be localized by
the translator. This URL does not have to exist but must not be used for later versions of the li-
cense. It is recommended to use URLs from [19] Open Source Initiative. Other licenses should use
the following structure, but this is not mandated:
http://<domain-name>/licenses/
<license-name>-<version>.<extension>
• description - (optional) Provide the description of the license. This is a short description that is
usable in a list box on a UI to select more information about the license.
• link - (optional) Provide a URL to a page that defines or explains the license. If this link is absent,
the name field is used for this purpose. The URL is relative to the root of the bundle. That is, it is
possible to refer to a file inside the bundle.
If the Bundle-License statement is absent, then this does not mean that the bundle is not licensed.
Licensing could be handled outside the bundle and the <<EXTERNAL>> form should be assumed.
This header is informational and may not have any legal bearing. Consult a lawyer before using this
header to automate licensing processing.
3.2.1.13 Bundle-ManifestVersion: 2
The Bundle-ManifestVersion header defines that the bundle follows the rules of this specification.
The Bundle-ManifestVersion header determines whether the bundle follows the rules of this specifi-
cation. It is 1 (the default) for Release 3 Bundles, 2 for Release 4 and later. Future version of the OSGi
framework can define higher numbers for this header.
See [27] Maven POM Reference, SCM for more information. Tools can use the information in this
header for POM generation.
A parameter can be either a directive or an attribute. A directive is an instruction that has some im-
plied semantics for the Framework. An attribute is used for matching and comparison purposes.
3.2.5 Version
Version specifications are used in several places. A version has the following grammar:
version ::=
major( '.' minor ( '.' micro ( '.' qualifier )? )? )?
A version must not contain any white space. The default value for a version is 0.0.0.
Versions are supported in the API with the Version class.
The Version annotation can be used in package-info.java source files to document the version of a
package. This annotation can be processed by bundle assembly tools when generating the version
information for a bundle's Export-Package manifest header.
If a version range is specified as a single version, it must be interpreted as the range [version,∞). The
default for a non-specified version range is 0, which maps to [0.0.0,∞).
Note that the use of a comma in the version range requires it to be enclosed in double quotes. For ex-
ample:
Import-Package: com.acme.foo;version="[1.23,2)", «
com.acme.bar;version="[4.0, 5.0)"
In the following table, for each specified range in the left-hand column, a version x is considered to
be a member of the range if the predicate in the right-hand column is true.
Example Predicate
[1.2.3, 4.5.6) 1.2.3 <= x < 4.5.6
[1.2.3, 4.5.6] 1.2.3 <= x <= 4.5.6
(1.2.3, 4.5.6) 1.2.3 < x < 4.5.6
(1.2.3, 4.5.6] 1.2.3 < x <= 4.5.6
1.2.3 1.2.3 <= x
Version Ranges are supported in the API with the VersionRange class.
The string representation of an LDAP search filter uses a prefix format and is defined by the follow-
ing grammar:
attr is a string representing an attribute key or name. Attribute names are not case sensitive; that is,
cn and CN both refer to the same attribute. attr must not contain the characters '=', '>', '<', '~', '(' or ')'.
attr may contain embedded spaces but leading and trailing spaces must be ignored.
value is a string representing the value, or part of one, which will be compared against a value in the
filtered properties.
If value must contain one of the characters reverse solidus ('\' \u005C), asterisk ('*' \u002A), paren-
theses open ('(' \u0028) or parentheses close (')' \u0029), then these characters should be preceded
with the reverse solidus ('\' \u005C) character. Spaces are significant in value. Space characters are
defined by Character.isWhiteSpace().
Although both the substring and present productions can produce the attr=* construct, this con-
struct is used only to denote a presence filter.
The substring production only works for attributes that are of type String, Collection of String or
String[]. In all other cases the result must be false.
The evaluation of the approximate match ('~=') filter type is implementation specific but should at
least ignore case and white space differences. Codes such as Soundex or other smart closeness com-
parisons could be used.
Values specified in the filter are compared to values in the properties against which the filter is eval-
uated. The comparison of these values is not straightforward. Strings compare differently than num-
bers, and it is also possible for a property to have multiple values.
Property keys are case insensitive. The object class of the property's value defines the comparison
type. The properties values should be of the following types:
Array and Collection elements may be a mix of scalar types. Array and Collection elements may al-
so be null. If the type of the property value is not one of the above types, then it could be possible to
create an instance of the above type. The following conversions must be tried in the given order:
1. A public static method on the required type called valueOf that returns an instance of the given
type and takes a single String argument.
2. A public constructor taking a single String argument.
If one of these methods is available then the Framework must construct a temporary object by pass-
ing the value as the String argument. If the constructor/function is not directly accessible then the
invocation should use the setAccessible method to make it accessible.
The resulting object must be used to compare with the property value according to the following
comparison rules:
If none of the above comparison rules apply, then the result of the comparison is false.
A filter matches a property with multiple values if it matches at least one of those values. For exam-
ple:
The dict will match against a filter with (cn=a) as well as (cn=b).
Service properties are often defined to take a type, a collection of that type, or an array of that type.
In those cases, a simple + will be suffixed to the type name. For example String+, indicates that a
String, a String[], and a Collection<String> are all valid forms.
Filters are supported in the API with the Filter type. Filters can be created with the
FrameworkUtil.createFilter(String) method or the BundleContext.createFilter(String) method.
Multi-Release: true
then the Framework must look for a supplemental manifest file, OSGI-INF/MANIFEST.MF, in the
versioned directories. For example:
META-INF/versions/9/OSGI-INF/MANIFEST.MF
The Framework must first look in the versioned directory for the major version of the current Java
platform and then prior versioned directories in descending order. The first supplemental manifest
file found must be used and the Framework must replace the values of the following manifest head-
ers in the manifest with the values of these headers, if present, in the supplemental manifest file.
• Import-Package
• Require-Capability
3.3 Dependencies
OSGi dependency handling is based on a very general model that describes the dependency relation-
ships. This model consists of a small number of primitive concepts:
Environment
<<interface>>
requirement
<<interface>> Namespace
Resource
<<interface>>
Capability
A Resource in general has dependencies on other Resources or can satisfy other Resource's depen-
dencies. Dependency types can vary wildly, a Bundle can require packages from another Bundle (Im-
port-Package), or a Fragment needs a host Bundle (Fragment-Host), or a Bundle requires access to
a high resolution display. The OSGi Core specification demonstrates that it is possible to describe
these varying types of dependencies with dedicated headers, optimized for each case. However, this
model requires that every type of dependency will go through a specification process, limiting the
usefulness for parties not participating in this process. Therefore, this specification provides a gener-
ic dependency model based on Namespaces. A Namespace is the type of a dependency. For example,
the osgi.wiring.package Namespace defines the semantics for Import-Package and Export-Package
headers by specifying a number of attributes and directives. Attributes are used for matching and di-
rectives provide information about the semantics of the Namespace. For example, in the case of the
osgi.wiring.host Namespace (Fragments) the capability's attributes are:
The OSGi Framework Namespaces are defined in classes, see Framework Namespaces Specification on
page 171.
The purpose of a Namespace is to create an attribute/directive based language that describes a de-
pendency in a generic way unrelated to the specific dependency type. A number of Namespaces
have been defined by the OSGi Alliance in this and other specifications. OSGi namespaces start with
the reserved osgi. prefix. For example, the osgi.ee namespace defines a capability for specifying an
execution environment. A Namespace can also be defined by other organizations and individuals.
To minimize name clashes it is recommended to use the reverse domain name rule used for pack-
ages and bundle symbolic names. It is also recommended to register these Namespaces with the OS-
Gi Alliance, see [17] OSGi Namespace Registry to prevent clashes.
Given a Namespace, it is possible to declare a capability of that Namespace. A capability provides the
values for the attributes and directives defined in the Namespace. For example, it is possible to trans-
late the Export-Package header to a capability in the osgi.wiring package Namespace.
Given a capability, it is possible to specify a requirement. A requirement has a filter that can match
the attributes of the capability, if so, the requirement is satisfied. Requirements are always associat-
ed with a given Namespace, like the capability, and can therefore only be satisfied by Capabilities
in the same Namespace. A requirement is satisfied when its filter, as specified with the filter direc-
tive, matches a capability's attributes. The filter language specification can be found in Filter Syntax
on page 39. A requirement can be mandatory or optional, as set with its resolution directive. A re-
quirement can have single or multiple cardinality, indicating it requires at least one or more Capabil-
ities.
A Resource that declares requirements can only provide its intended functionality when its manda-
tory requirements are satisfied by one or more Capabilities, which in general means they come from
other Resources. A Resource that has all its mandatory requirements satisfied is said to be resolved
and must provide the functionality described by its Capabilities. A capability can only satisfy a re-
quirement if its Resource is resolved.
The process of matching up requirements to capabilities is called resolving. In this process, the re-
solver must create Wires that link requirements to Capabilities. Both the Wire and the requirement/
Capability have a reference to a Resource. In certain cases the requirement/ capability can be de-
clared in one Resource but wired from another Resource. Therefore, a requirement/ capability can
have a declared Resource, which is the Resource that declares it. However, when a Resource is wired
the Wire has a provider or requirer Resource which can differ from the corresponding declared Re-
source. When the declared Resource differs from the provider/requirer it is called hosting. This sepa-
ration is caused by Fragments; with Fragments some requirements and Capabilities are hosted and
others remain part of the Fragment.
Only requirements that are effective must be wired. Each requirement is intended for a certain state
of the system. For example, the OSGi Framework only resolves requirements when the requirement
has the effective directive set to resolve.
Once a set of Resources are resolved the Environment, for example the OSGi Framework for bun-
dles, creates a Wiring per Resource to hold the resolved state. This state includes the Wires as well as
all Capabilities and requirements, regardless if they are wired or not.
The Wires between a requirement and a capability must be created according to the semantics im-
plied by their Namespace. The Wires coming out of a resolve operation can be used during run time
as specified in their Namespace. For example, the osgi.wiring.* Namespaces are used to control the
Class Loading, see Bundle Wiring API Specification on page 157. However, they can also serve other
purposes as outlined by their Namespace. For example, a Wire could specify a Dependency Injection
source and target.
Interfaces for the generic model are defined in Resource API Specification on page 151. The Bundle
Wiring API Specification on page 157 chapter describes the Wiring API that is based on this gener-
ic package. The generic API is intended for other specifications that want to be compatible with the
generic OSGi Core framework's Capability /Requirement model.
3.3.1 Bundles
All bundles depend on one or more external entities and this is expressed as requirements and Capa-
bilities. Once a bundle is resolved, it assumes that those dependencies are satisfied. The Require-Ca-
pability and Provide-Capability headers are manifest headers that declare generic requirements and
Capabilities in any Namespace. However, a number of manifest headers in the OSGi specifications
are actually requirements on Capabilities specified by other OSGi manifest headers. For example,
an Import-Package clause is a requirement on the capability specified by an Export-Package clause.
The attributes on an Import-Package clause are treated as assertions on the attributes of the corre-
sponding Export-Package clause. This specification therefore contains a number of Namespaces for
these OSGi manifest headers: osgi.wiring.bundle, osgi.wiring.package, and osgi.wiring.host. These
namespaces influence the resolver and define the class loading process. For example, a Require-Bun-
dle clause is a requirement that ensures that the exported packages of the required bundle are avail-
able to the requirer's class loader.
The OSGi resolving process is described in Resolving Process on page 65. The diagramming tech-
nique of the Requirement/Capability model is depicted in Figure 3.3, the details of the wiring are
further explained in Bundle Wiring API Specification on page 157.
Requirement
Capability
Bundle
Requirement/Capability
host fragment Runtime
Require-Capability:
com.microsoft; filter:="(&(api=win32)(version=7))",
com.acme.display; filter:="(&(width>=1000)(height>=1000))",
com.acme.ip2loc
Each clause lives in a namespace, for example com.microsoft. A namespace defines the semantics of
the attributes as well as optional rules.
The deployer of the environment sets the following launching property when starting the frame-
work:
org.osgi.framework.system.capabilities.extra= «
com.acme.display; width:Long=1920; height:Long=1080; interlace=p, «
com.microsoft; edition=home; version:Version=7; api=win32
The framework will be able to satisfy the display requirement but it cannot satisfy the ip2loc table
requirement. The deployer can then install the bundle with the ip2loc table. This bundle specifies
the following header:
After installing and resolving this bundle, the framework can resolve the original bundle because
there is now a provider of the ip2loc table.
The Capability annotation can be used on a class or package to specify a capability to be provided by
the bundle. This annotation can be processed by bundle assembly tools to add the capability to the
Provide-Capability header in the bundle's manifest.
The header has the following directives architected:
• effective - (resolve) Specifies the time a capability is available, either resolve (default) or another
name. The OSGi framework resolver only considers Capabilities without an effective directive or
effective:=resolve. Capabilities with other values for the effective directive can be considered by
an external agent.
• uses - The uses directive lists package names that are used by this capability. This information is
intended to be used for uses constraints, see Package Constraints on page 60.
attr:Long=24
attr:Long= 23 , //ok
attr:Version=" 23 ", // error
attr:Long=" 23 ", // ok, because nummeric
Multi-valued attributes can be constructed with the List type. The List type can specify a scalar type
for the list elements. If no element type is specified, String is assumed. Parsing of the corresponding
argument list must be done according to the following rules:
The whole argument must be surrounded by quotes because the comma is a significant token in the
manifest grammar.
The version attribute requires the Version type to be specified to be compared as a Version rather
than as a String:
version:Version=1.23
For example:
Provide-Capability: «
com.acme.dictionary; from:String=nl; to=de; version:Version=3.4, «
com.acme.dictionary; from:String=de; to=nl; version:Version=4.1, «
com.acme.ip2location;country:List="nl,be,fr,uk";version:Version=1.3, «
com.acme.seps; tokens:List<String>="\\,,;,\\\""
org.osgi.framework.system.capabilities
org.osgi.framework.system.capabilities.extra
The format for these system properties is identical to the Provide-Capability header. A framework
must parse these properties and use them in the resolving process as if provided by the system bun-
dle.
There are two properties so that the framework can specify its default Capabilities in
org.osgi.framework.system.capabilities while the deployer can specify specific deployment Capa-
bilities in the org.osgi.framework.system.capabilities.extra system property. Frameworks can often
deduce many Capabilities from their environment.
The following is an example capability header for the system bundle as defined by the deployer:
map.put("org.osgi.framework.system.capabilities.extra",
"com.acme.screen; width:Long=640; height:Long=480; card=GeForce");
Requirements have attributes that can be set with the Require-Capability header. The purpose of
these attributes are to provide further information about the requirement; they are not assertions as
they are in the Import-Package, Require-Bundle, and Fragment-Host headers. The attributes of these
headers are mapped to the filter directive in their corresponding namespaces.
The Requirement annotation can be used on a class or package to specify a capability to be required
by the bundle. This annotation can be processed by bundle assembly tools to add the requirement to
the Require-Capability header in the bundle's manifest.
The following directives are architected for the Require-Capability header:
• effective - (resolve) Specifies the time a requirement is considered, either resolve (default) or an-
other name. The OSGi framework resolver only considers requirements without an effective di-
rective or effective:=resolve. Other requirements can be considered by an external agent. Addi-
tional names for the effective directive should be registered with the OSGi Alliance.
• resolution - (mandatory|optional) A mandatory requirement forbids the bundle to resolve when
the requirement is not satisfied; an optional requirement allows a bundle to resolve even if the
requirement is not satisfied. No wirings are created when this requirement cannot be resolved,
this can result in Class Not Found Exceptions when the bundle attempts to use a package that
was not resolved because it was optional. The default is mandatory.
• filter - (Filter) A filter expression that is asserted on the Capabilities belonging to the given name-
space. The matching of the filter against the capability is done on one capability at a time. A fil-
ter like (&(a=1)(b=2)) matches only a capability that specifies both attributes at the required val-
ue, not two capabilities that each specify one of the attributes correctly. A filter is optional, if no
filter directive is specified the requirement always matches. The attribute names in the filter ex-
pression are used to locate capability attributes in a case sensitive manner.
• cardinality - (single|multiple) Indicates if the requirement can be wired a single time or multiple
times. The default is single.
Additional directives are ignored during resolving. Attributes on the requirement clause are also ig-
nored.
3.4.1 Bundle-RequiredExecutionEnvironment
The Bundle-RequiredExecutionEnvironment manifest header provides the same function as the
osgi.ee Namespace on page 172. It allows a bundle to depend on the execution environment. This
header is deprecated but must be fully supported by a compliant framework. Bundles should not
mix these headers but use either an osgi.ee requirement or this header. If both are used, both con-
straints must be met to resolve.
For example:
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0, «
OSGi/Minimum-1.1
If a bundle includes this header in the manifest then the bundle must only use methods with signa-
tures that are contained within a proper subset of all mentioned execution environments. Bundles
should list all (known) execution environments on which it can run the bundle.
A bundle can only resolve if the framework is running on a VM which implements one of the list-
ed required execution environments. Frameworks should recognize that the current VM can imple-
ment multiple execution environments. For example, Java 6 is backward compatible with Java 5 and
a bundle requiring the Java 6 execution environment must resolve on a Java 6 VM.
The Bundle-RequiredExecutionEnvironment header can not prevent a bundle from installing.
The org.osgi.framework.executionenvironment launching property defines the current execution
environment with a comma separated list of execution environment names. If not set, the frame-
work must provide an appropriate value. This property is also deprecated, its function is replaced
with org.osgi.framework.system.capabilities[.extra].
An example:
org.osgi.framework.executionenvironment =
JavaSE-1.5, J2SE-1.4, JavaSE-1.4, JavaSE-1.3, OSGi/Minimum-1.1
For example:
CDC-1.0/Foundation-1.0
OSGi/Minimum-1.2
J2SE-1.4
JavaSE-1.4
Each bree term that matches this pattern can thus be converted into an equivalent osgi.ee Re-
quire-Capability filter. First variable n1 must be replaced with JavaSE when it is J2SE since the Re-
quire-Capability header uses a single name for the Java Standard Edition. The filter directive can
then be constructed from n1, v, and n2. If n2 is not defined or v is not defined then the parenthesized
parts in which they participate are not used in the expansion.
If the bree term cannot be parsed into the given constituents then the filter must look like:
Some examples:
CDC-1.0/Foundation-1.0 (&(osgi.ee=CDC/Foundation)(version=1.0))
OSGi/Minimum-1.2 (&(osgi.ee=OSGi/Minimum)(version=1.2))
J2SE-1.4 (&(osgi.ee=JavaSE)(version=1.4))
JavaSE-1.6 (&(osgi.ee=JavaSE)(version=1.6))
AA/BB-1.7 (&(osgi.ee=AA/BB)(version=1.7))
V1-1.5/V2-1.6 (osgi.ee=V1-1.5/V2-1.6)
MyEE-badVersion (osgi.ee=MyEE-badVersion)
Bundle-RequiredExecutionEnvironment:
CDC-1.0/Foundation-1.0,
OSGi/Minimum-1.2,
J2SE-1.4,
JavaSE-1.6,
AA/BB-1.7,
V1-1.5/V2-1.6,
MyEE-badVersion
Require-Capability:osgi.ee; filter:="(|
(&(osgi.ee=CDC/Foundation)(version=1.0))
(&(osgi.ee=OSGi/Minimum)(version=1.2))
(&(osgi.ee=JavaSE)(version=1.4))
(&(osgi.ee=JavaSE)(version=1.6))
(&(osgi.ee=AA/BB)(version=1.7))
(osgi.ee=V1-1.5/V2-1.6)
(osgi.ee=MyEE-badVersion)
)"
importer exporter
Bundle
class loader
Bundle
class loader
Parent/System
class loader
Bundle
class loader
Bundle System Bundle
class loader class loader
• Boot class path - The boot class path contains the java.* packages and its implementation pack-
ages.
• Framework class path - The Framework usually has a separate class loader for the Framework im-
plementation classes as well as key service interface classes.
• Bundle Space - The bundle space consists of the JAR file that is associated with the bundle, plus
any additional JAR that are closely tied to the bundle, like fragments, see Fragment Bundles on page
87.
A class space is then all classes reachable from a given bundle's class loader. Thus, a class space for a
given bundle can contain classes from:
• The parent class loader (normally java.* packages from the boot class path)
• Imported packages
• Required bundles
• The bundle's class path (private packages)
• Attached fragments
A class space must be consistent, such that it never contains two classes with the same fully quali-
fied name (to prevent Class Cast Exceptions). However, separate class spaces in an OSGi Platform
may contain classes with the same fully qualified name. The modularization layer supports a model
where multiple versions of the same class are loaded in the same VM.
Figure 3.5 shows the class space for a Bundle A. The right top of Bundle A is not in the class space be-
cause it illustrates that sometimes packages inside a bundle are not accessible to the Bundle itself
when an export is substituted.
Bundle B
public
private
private
Bundle A
public public
public
private
Bundle C
The Framework therefore has a number of responsibilities related to class loading. Before a bundle is
used, it must resolve the constraints that a set of bundles place on the sharing of packages. Then se-
lect the best possibilities to create a wiring. See Resolving Process on page 65 for further informa-
tion. The runtime aspects are described in Runtime Class Loading on page 67.
3.5.1 Resolving
The Framework must resolve bundles. Resolving is the process where any external dependencies are
satisfied and then importers are wired to exporters. Resolving is a process of satisfying constraints;
constraints that are provided by the Dependencies on page 42 section and constraints by the dif-
ferent manifest headers like Import/Export Package, Require-Bundle, and Fragment-Host. The resolv-
ing process must take place before any code from a bundle can be loaded or executed.
A wire is an actual connection between an exporter and an importer, which are both bundles. A wire
is associated with a number of constraints that are defined by its importer's and exporter's manifest
headers. A valid wire is a wire that has satisfied all its constraints. Figure 3.6 depicts the class struc-
ture of the wiring model. Not all constraints result in a wire.
Figure 3.6 Example class structure of wiring
3.6.1 Bundle-ManifestVersion
A bundle manifest must express the version of the OSGi manifest header syntax in the Bundle-Man-
ifestVersion header. Bundles exploiting this version of the Framework specification (or later) must
specify this header. The syntax of this header is as follows:
The Framework bundle manifest version must be '2'. Bundle manifests written to previous specifica-
tions' manifest syntax are taken to have a bundle manifest version of '1', although there is no way to
express this in such manifests. Therefore, any other value than 2 for this header is invalid unless the
Framework explicitly supports such a later version.
OSGi Framework implementations should support bundle manifests without a Bundle-ManifestVer-
sion header and assume Framework 1.2 compatibility at the appropriate places.
Version 2 bundle manifests must specify the bundle symbolic name. They need not specify the bun-
dle version because the version header has a default value.
3.6.2 Bundle-SymbolicName
The Bundle-SymbolicName manifest header is a mandatory header. The bundle symbolic name and
bundle version identify a unique bundle. This does not always imply that this pair is unique in a
framework, in certain cases the same bundle can be installed multiple times in the same framework,
see Bundle Identifiers on page 113.
A bundle gets its unique Bundle-SymbolicName from the developer. The Bundle-Name manifest
header provides a human-readable name for a bundle and is therefore not replaced by this header.
The Bundle-SymbolicName manifest header must conform to the following syntax:
The framework must recognize the following directives for the Bundle-SymbolicName header:
• singleton - Indicates that the bundle can only have a single version resolved in an environment.
A value of true indicates that the bundle is a singleton bundle. The default value is false. The
Framework must resolve at most one bundle when multiple versions of a singleton bundle with
the same symbolic name are installed. Singleton bundles do not affect the resolution of non-sin-
gleton bundles with the same symbolic name.
• fragment-attachment - Defines how fragments are allowed to be attached, see the fragments in
Fragment Bundles on page 87. The following values are valid for this directive:
• always - (Default) Fragments can attach at any time while the host is resolved or during the
process of resolving.
• never - No fragments are allowed.
• resolve-time - Fragments must only be attached during resolving.
• mandatory - Provide a list of mandatory attributes. If these attributes are not specifically used in
the requirement (Require-Bundle, Fragment-Host) then this bundle must not match. See Manda-
tory Attributes on page 63.
The header allows the use of arbitrary attributes that can be required by the Require-Bundle and
Fragment-Host headers. The following attribute is predefined:
• bundle-version - The value of the Bundle-Version header or 0 if no such header is present. Explic-
itly setting this attribute is an error.
For example:
Bundle-SymbolicName: com.acme.foo;singleton:=true
3.6.3 Bundle-Version
Bundle-Version is an optional header; the default value is 0.0.0.
If the minor or micro version components are not specified, they have a default value of 0. If the
qualifier component is not specified, it has a default value of the empty string ("").
Versions are comparable. Their comparison is done numerically and sequentially on the major, mi-
nor, and micro components and lastly using the String class compareTo method for the qualifier.
A version is considered equal to another version if the major, minor, micro, and the qualifier compo-
nents are equal (using String method compareTo).
Example:
Bundle-Version: 22.3.58.build-345678
3.6.4 Import-Package
The Import-Package header defines the constraints on the imports of shared packages. The syntax of
the Import-Package header is:
The header allows many packages to be imported. An import definition is the description of a single
package for a bundle. The syntax permits multiple package names, separated by semi-colons, to be
described in a short form.
Import package directives are:
• resolution - Indicates that the packages must be resolved if the value is mandatory, which is the
default. If mandatory packages cannot be resolved, then the bundle must fail to resolve. A value
of optional indicates that the packages are optional. See Optional Packages on page 60.
The developer can specify arbitrary matching attributes. See Attribute Matching on page 63. The
following arbitrary matching attributes are predefined:
• version - A version-range to select the exporter's package version. The syntax must follow Ver-
sion Ranges on page 39. For more information on version selection, see Semantic Versioning on
page 58. If this attribute is not specified, it is assumed to be [0.0.0, ∞).
• specification-version - This attribute is an alias of the version attribute only to ease migration
from earlier versions. If the version attribute is present, the values must be equal.
• bundle-symbolic-name - The bundle symbolic name of the exporting bundle. In the case of a
fragment bundle, this will be the host bundle's symbolic name.
• bundle-version - A version-range to select the bundle version of the exporting bundle. The de-
fault value is [0.0.0, ∞). See Semantic Versioning on page 58. In the case of a fragment bundle,
the version is from the host bundle.
Import-Package: com.acme.foo;com.acme.bar; «
version="[1.23,1.24]"; «
resolution:=mandatory
3.6.5 Export-Package
The syntax of the Export-Package header is similar to the Import-Package header; only the directives
and attributes are different.
The header allows many packages to be exported. An export definition is the description of a single
package export for a bundle. The syntax permits the declaration of multiple packages in one clause
by separating the package names with a semi-colon. Multiple export definitions for the same pack-
age are allowed for example, when different attributes are needed for different importers. The Export
annotation can be applied to a package to specify the package is to be exported. This annotation can
be processed by bundle assembly tools to add the annotated package to the Export-Package header
in the bundle's manifest.
Export directives are:
• uses - A comma-separated list of package names that are used by the exported package. Note that
the use of a comma in the value requires it to be enclosed in double quotes. If this exported pack-
age is chosen as an export, then the resolver must ensure that importers of this package wire to
the same versions of the package in this list. See Package Constraints on page 60.
• mandatory - A comma-separated list of attribute names. Note that the use of a comma in the val-
ue requires it to be enclosed in double quotes. A bundle importing the package must specify the
mandatory attributes, with a value that matches, to resolve to the exported package. See Manda-
tory Attributes on page 63.
• include - A comma-separated list of class names that must be visible to an importer. Note that
the use of a comma in the value requires it to be enclosed in double quotes. For class filtering, see
Class Filtering on page 63.
• exclude -A comma-separated list of class names that must be invisible to an importer. Note that
the use of a comma in the value requires it to be enclosed in double quotes. For class filtering, see
Class Filtering on page 63.
• version - The version of the named packages with syntax as defined in Version on page 38. It
defines the version of the associated packages. The default value is 0.0.0.
• specification-version - An alias for the version attribute only to ease migration from earlier ver-
sions. If the version attribute is present, the values must be equal.
Additionally, arbitrary matching attributes may be specified. See Attribute Matching on page 63.
The Framework will automatically associate each package export definition with the following at-
tributes:
• bundle-symbolic-name - The bundle symbolic name of the exporting bundle. In the case of a
fragment bundle, this is the host bundle's symbolic name.
• bundle-version - The bundle version of the exporting bundle. In the case of a fragment bundle,
this is the host bundle's version.
An installation or update must be aborted when any of the following conditions is true:
An export definition does not imply an automatic import definition. A bundle that exports a pack-
age and does not import that package will get that package via its bundle class path. Such an export-
ed only package can be used by other bundles, but the exporting bundle does not accept a substitu-
tion for this package from another bundle.
In order to export a package, a bundle must have PackagePermission[<package>, EXPORTONLY].
Example:
Export-Package: com.acme.foo;com.acme.bar;version=1.23
• The exported package does not use private packages. If an exported package uses private pack-
ages then it might not be substitutable and is therefore not clean API.
• There is at least one private package that references the exported package. If no such reference
exist, there is no purpose in importing it.
In practice, importing exported packages can only be done with clean API-implementation separa-
tion. OSGi services are carefully designed to be as standalone as possible. Many libraries intertwine
API and implementation in the same package making it impossible to substitute the API packages.
Importing an exported package must use a version range according to its compatibility require-
ments, being either a consumer or a provider of that API. See Semantic Versioning on page 58 for
more information.
• Import-Package - An import definition must change the specification-version attribute to the ver-
sion attribute. An import definition without a specification version needs no replacement since
the default version value of 0.0.0 gives the same semantics as Release 3.
• Export-Package - An export definition must change the specification-version attribute to the
version attribute. The export definition must be appended with the uses directive. The uses di-
rective must contain all imported and exported packages for the given bundle. Additionally, if
there is no import definition for this package, then an import definition for this package with
the package version must be added.
• DynamicImport-Package - A dynamic import definition is unmodified.
A bundle manifest which mixes legacy syntax with bundle manifest version 2 syntax is in error and
must cause the containing bundle to fail to install.
The specification-version attribute is a deprecated synonym for the version attribute in bundle
manifest version 2 headers.
fragment host
bundle
For example:
A: Import-Package: p; version="[1,2)"
Export-Package: q; version=2.2.2; uses:=p
Require-Bundle: C
B: Export-Package: p; version=1.5.1
C: Export-Package: r
q-2.2.2 r C
A
p s
version=[1,2)
B p-1.5.1
A: Import-Package: p; version="[1,2)"
B: Export-Package: p; version=1.5.1
A version=[1,2) B
p p-1.5.1
C
p-2.4.3
A provider of an API is closely bound to that API. Virtually any change to that API makes a provider
implementation incompatible with the new version of the API. However, API changes have more
leeway from the perspective of a consumer of that API. Many API changes can be made backward
compatible for consumers but hardly any API change can be made backward compatible for a
provider of that API.
A provider of an API should therefore import that API with a smaller range than a consumer of that
API. This policy can be encoded in a version range. The rules are summarized as follows:
• major - Changes for an incompatible update for both a consumer and a provider of an API.
• minor - Changes for a backward compatible update for a consumer but not for a provider.
• micro - A change that does not affect the API, for example, a typo in a comment or a bug fix in an
implementation.
Both consumers and providers should use the version they are compiled against as their base ver-
sion. It is recommended to ignore the micro part of the version because systems tend to become
very rigid if they require the latest bug fix to be deployed all the time. For example, when compiled
against version 4.2.1.V201007221030, the base version should be 4.2.
A consumer of an API should therefore import a range that starts with the base version and ends
with the next major change, for example: [4.2,5). A provider of an API should import a range that
starts with the base version up to the next minor change, for example: [4.2,4.3).
• Dynamic Imports - The DynamicImport-Package header is intended to look for an exported pack-
age when that package is needed. The key use case for dynamic import is the Class forName
method when a bundle does not know in advance the class name it may be requested to load.
• Resolution Directive - The resolution directive on an import definition specifying the value option-
al. A bundle may successfully resolve if a suitable optional package is not present.
The key difference between these two mechanisms is when the wires are made. An attempt is made
to establish a wire for a dynamic import every time there is an attempt to load a class in that pack-
age, whereas the wire for a resolution optional package may only be established when the bundle is
resolved.
The resolution directive of the import definition can take the value mandatory or optional.
• mandatory - (Default) Indicates that the package must be wired for the bundle to resolve.
• optional - Indicates that the importing bundle may resolve without the package being wired. If
the package is not wired, the class loading will treat this package as if it is not imported.
The following example will resolve even though bundle B does not provide the correct version (the
package will not be available to the code when bundle A is resolved).
A: Import-Package: p; «
resolution:=optional; «
version=1.6
B: Export-Package: p; «
q; «
version=1.5.0
A p version=1.6 p-1.5.0 B
q-1.5.0
The implementation of a bundle that uses optional packages must be prepared to handle the fact
that the packages may not be available: that is, an exception can be thrown when there is a refer-
ence to a class from a missing package. This can be prevented by including a fallback package on the
bundle's class path. When an optional package cannot be resolved, any attempts by the bundle to
load classes from it will follow normal bundle class loading search order as if the import never exist-
ed. It will load it from the bundle's class path or in the end through dynamic class loading when set
for that bundle and package.
For example, org.osgi.service.http depends on the package javax.servlet because it is used in the
API. The export definition of the org.osgi.service.http must therefore contain the uses directive
with the javax.servlet package as its value.
Class space consistency can only be ensured if a bundle has only one exporter for each
package. For example, the Http Service implementation requires servlets to extend the
javax.servlet.http.HttpServlet base class. If the Http Service bundle would import version 2.4 and
the client bundle would import version 2.1 then a class cast exception is bound to happen. This is
depicted in Figure 3.11.
A org.osgi.service.http org.osgi.service.http B
p javax.servlet.http
javax.servlet.http
If a bundle imports a package from an exporter then the export definition of that package can imply
constraints on a number of other packages through the uses directive. The uses directive lists the
packages that the exporter depends upon and therefore constrains the resolver for imports. These
constraints ensure that a set of bundles share the same class loader for the same package.
When an importer imports a package with uses constraints, the resolver must wire the import to
the exporter named in the uses constraint. This exporter may in turn imply additional constraints,
and so on. The act of wiring a single import of a package to an exporter can therefore imply a large
set of constraints. The term implied package constraints refers to the complete set of constraints con-
structed from recursively traversing the wires. Implied package constraints are not automatic im-
ports; rather, implied package constraints only constrain how an import definition must be wired.
For example, in Figure 3.12, bundle A imports package p. Assume this import definition is wired to
bundle B. Due to the uses directive (the ellipse symbols indicates the uses directive) this implies a
constraint on package q.
Further, assuming that the import for package q is wired to bundle C, then this implies a constraint
on the import of package r and s. Continuing, assuming C.s and C.r are wired to bundle D and E re-
spectively. These bundles both add package t to the set of implied packages for bundle A.
A p p B
t q
C
q
r
s
F D E
t s r
t t
t
To maintain class space consistency, the Framework must ensure that none of its bundle imports
conflicts with any of that bundle's implied packages.
For the example, this means that the Framework must ensure that the import definition of A.t is
wired to package D.t. Wiring this import definition to package F.t violates the class space consis-
tency. This violation occurs because bundle A could be confronted with objects with the same class
name but from the class loaders of bundle D and F. This would potentially create ClassCastExcep-
tions. Alternatively, if all bundles are wired to F.t, then the problem also goes away.
Another scenario with this case is depicted in Figure 3.11. Bundle A imports the Http Service classes
from bundle B. Bundle B has grouped the org.osgi.service.http and the javax.servlet and bundle A is
therefore constrained to wire javax.servlet to the same exporter as bundle B.
As an example of a situation where the uses directive makes resolving impossible consider the fol-
lowing setup that is correctly resolved:
A: Import-Package: q; version="[1.0,1.0]"
Export-Package: p; uses:="q,r",r
B: Export-Package: q; version=1.0
C: Export-Package: q; version=2.0
These specific constraints can be resolved because the import A.q can be wired to the export B.q but
not C.q due to the version constraint.
Adding a bundle D will now not be possible:
D: Import-Package: p, q; version=2.0
Package D.p must be wired to package A.p because bundle A is the only exporter. However, this im-
plies the use of package q due the uses directive in the package A.q import. Package A.q is wired to
B.q-1.0. However, import package D.q requires version 2.0 and can therefore not be resolved with-
out violating the class space constraint.
This scenario is depicted in Figure 3.13.
A version=1.0 B
q q-1.0
p
p D
r version=2 C
q q-2.0
A: Import-Package: com.acme.foo;company=ACME
B: Export-Package: com.acme.foo; «
company="ACME"; «
security=false
Attribute values are compared string wise except for the version and bundle-version attributes
which use version range comparisons. Leading and trailing white space in attribute values must be
ignored.
Attribute matching also works for the Require-Bundle and Fragment-Host headers; the attributes to
be matched are specified on the Bundle-SymbolicName header.
A: Import-Package: com.acme.foo;company=ACME
B: Export-Package: com.acme.foo; «
company="ACME"; «
security=false; «
mandatory:=security
Class names must not include their package name and do not end with .class. That is, the class
com.acme.foo.Daffy is named Daffy in either list. The class name can include multiple wildcard as-
terisks ('*' \u002A).
The default for the include directive is an asterisk ('*' \u002A) (wildcard matching all names), and
for the exclude directive, so that no classes are excluded, an empty list that matches no names. If in-
clude or exclude directive are specified, the corresponding default is overridden.
A class is only visible if it is:
In all other cases, loading or finding fails, and a Class Not Found Exception is thrown for a class load.
The ordering of include and exclude is not significant.
The following example shows an export statement, and a list of files with their visibility status.
com/acme/foo
QuxFoo visible
QuxBar visible
QuxImpl excluded
BarImpl visible
Care must be taken when using filters. For example, a new version of a module that is intended to be
backward compatible with an earlier version should not filter out classes that were not filtered out
by the earlier version. In addition, when modularizing existing code, filtering out classes from an ex-
ported package may break users of the package.
For example, packages defined by standard bodies often require an implementation class in the stan-
dardized package to have package access to the specification classes.
package org.acme.open;
public class Specified {
static Specified implementation;
public void foo() { implementation.foo(); }
}
package org.acme.open;
public class Implementation {
public void initialize(Specified implementation) {
Specified.implementation = implementation;
}
}
The Implementation class must not be available to external bundles because it allows the imple-
mentation to be set. By excluding the Implementation class, only the exporting bundle can see this
class. The export definition for this header could look like:
porter. The importer tightly couples itself to a specific exporter, typically the bundle that was used
for testing. To make the wiring less brittle, the importer can optionally specify a range of bundle ver-
sions that will match.
An importer can select an exporter with the import attributes bundle-symbolic-name and bun-
dle-version. The Framework automatically provides these attributes for each export definition.
These attributes must not be specified in an export definition.
The export definition bundle-symbolic-name attribute will contain the bundle symbolic name as
specified in the Bundle-SymbolicName header without any parameters. The export definition bun-
dle-version attribute is set to the value of the Bundle-Version header or its default of 0.0.0 when ab-
sent.
The bundle-symbolic-name is matched as an attribute. The bundle-version attribute is matched us-
ing the version range rules as defined in Version Ranges on page 39. The import definition must
be a version range and the export definition is a version.
For example, the following definitions will match:
A: Bundle-SymbolicName: A
Import-Package: com.acme.foo; «
bundle-symbolic-name=B; «
bundle-version="[1.41,2.0.0)"
B: Bundle-SymbolicName: B
Bundle-Version: 1.41
Export-Package: com.acme.foo
The following statements will not match because bundle B does not specify a version and thus de-
faults to 0.0.0:
A: Bundle-SymbolicName: A
Import-Package: com.acme.foo; «
bundle-symbolic-name=B; «
bundle-version="[1.41,2.0.0)"
B: Bundle-SymbolicName: B
Export-Package: com.acme.foo;version=1.42
Selecting an exporter by symbolic name can result in brittleness because of hard coupling of the
package to the bundle. For example, if the exporter eventually needs to be refactored into multiple
separate bundles, all importers must be changed. Other arbitrary matching attributes do not have
this disadvantage as they can be specified independently of the exporting bundle.
The brittleness problem of the bundle symbolic name in bundle refactoring can be partly overcome
by writing a façade bundle using the same bundle symbolic name as the original bundle.
• Any mandatory requirement must be matched to at least one capability in the same namespace
provided by any of the resolved bundles, including itself and the system bundle.
• The required execution environments as defined by the Bundle-RequiredExecutionEnvironment
header.
• Native code
• Import and export packages (the DynamicImport-Package header is ignored in this phase)
• Required bundles, which import all exported packages from a bundle as defined in Requiring Bun-
dles on page 84.
• Fragments, which provide their contents and definitions to the host as defined in Fragment Bun-
dles on page 87
• Execution Environment - The underlying VM implements at least one of the execution environ-
ments listed in the Bundle-RequiredExecutionEnvironment header. See osgi.ee Namespace on page
172.
• Native code - The native code dependencies specified in the Bundle-NativeCode header must be re-
solved. See Loading Native Code Libraries on page 76.
The resolving process is then a constraint-solving algorithm that can be described in terms of re-
quirements on wiring relations. The resolving process is an iterative process that searches through
the solution space.
A bundle can be resolved if the following conditions are met:
• The importer's version range matches the exporter's version. See Semantic Versioning on page
58.
• The importer specifies all mandatory attributes from the exporter. See Mandatory Attributes on
page 63.
• All the importer's attributes match the attributes of the corresponding exporter. See Attribute
Matching on page 63
• Implied packages referring to the same package as the wire are wired to the same exporter. See
Package Constraints on page 60.
• The wire is connected to a valid exporter.
The following list defines the preferences, if multiple choices are possible, in order of decreasing pri-
ority:
• External - If this resolves to an export statement in another bundle, then the overlapping export
definition in this bundle is discarded.
• Internal - If it is resolved to an export statement in this bundle, then the overlapping import defi-
nition in this bundle is discarded.
• Unresolved - There is no matching export definition. In this case the framework is free to discard
either the overlapping export definition or overlapping import definition in this bundle. If the
export definition is discarded and the import definition is not optional then the bundle will fail
to resolve.
The above only applies to the import and export package definitions of a bundle. For namespaces
other than osgi.wiring.package, a requirement definition of a bundle may be wired to a capability
definition of that same bundle.
This search order is called the entry path. A resource (or class) is not loaded via the entry path, but it
is loaded through the bundle class path. The bundle class path provides an additional indirection on
top of the entry path. It defines an ordered list of container paths. Each container path can be found
on the entry path.
Each container, independent of any other containers, can be a multi-release container. See Multi-re-
lease Container on page 69.
The full stop ('.' \u002E) container path is a synonym for the solidus ('/' \u002F) or the root of a con-
tainer. The full stop is the default value for a bundle or fragment if no Bundle-ClassPath header is
specified.
The Bundle-ClassPath manifest header must conform to the following syntax:
An element from the bundle's Bundle-ClassPath header refers to the first match when searched
through the entry path, while a fragment's Bundle-ClassPath can refer only to an entry in its own
container.
An example can illustrate this:
A: Bundle-ClassPath: .,resource.jar
B: Fragment-Host: A
/, resource.jar, B:/
The first element / is the root of a container. The bundle always has a root and can therefore always
be found in the (host) bundle. The second element is first looked up in the host bundle's container,
and if not found, the entry is looked up in the container of B. The Framework must use the first en-
try that matches. The last element in the effective bundle class path is the / from fragment B; the / is
the default because there is no Bundle-ClassPath specified. However, a fragment can only refer to an
internal entry. This full stop therefore refers to the root of the container of fragment B. Assuming,
fragment B contains an entry for resource.jar and bundle A does not, then the search order must be:
A:/
B:resource.jar
B:/
The Framework must ignore a container path in the bundle class-path if the container cannot be lo-
cated when it is needed, which can happen at any time after the bundle is resolved. However, the
Framework should publish a Framework Event of type INFO once with an appropriate message for
each entry that cannot be located at all.
An entry on the Bundle-ClassPath can refer to a directory in the container. However, it is not always
possible to establish the directory's existence. For example, directories can be omitted in JAR/ZIP
files. In such a case, a Framework must probe the directory to see if any resources can be found in
this directory. That is, even if the directory construct is absent in the container, if resources can be
found assuming this directory, than it must still be chosen for the Bundle-ClassPath.
A host bundle can allow a fragment to insert code ahead of its own code by naming a container in
its Bundle-ClassPath that will be provided by a fragment. Fragments can never unilaterally insert
code ahead of their host's bundle class path. The following example illustrates the possibilities of
the bundle class path in more detail:
A: Bundle-SymbolicName: A
Bundle-ClassPath: /,required.jar,optional,default.jar
content ...
required.jar
default.jar
B: Bundle-SymbolicName: B
Bundle-ClassPath: fragment.jar
Fragment-Host: A
content ...
optional/
content ...
fragment.jar
The names of the bundle class path elements indicate their intention. The required.jar is a container
that provides mandatory functionality, it is packaged in bundle A. The optional container is a direc-
tory containing optional classes, and the default.jar is a JAR entry with backup code. In this exam-
ple, the effective bundle class path is:
A:/
A:required.jar
B:optional
A:default.jar
B:fragment.jar
This will expand to the following (logical) search order for a resource X.class:
A:/X.class
A:required.jar!X.class
B:optional/X.class
A:default.jar!X.class
B:fragment.jar!X.class
Multi-Release: true
then the Framework must search the container's versioned directories when attempting to locate an
entry in the container.
Support for multi-release containers must only be active on Java 9 and later. On Java 8 and earlier,
the container must be treated as a non-multi-release container.
No directives are architected by the Framework for DynamicImport-Package. Arbitrary matching at-
tributes may be specified. The following matching attributes are architected by the Framework:
• version -- A version range to select the version of an export definition. The default value is 0.0.0 .
• bundle-symbolic-name - The bundle symbolic name of the exporting bundle.
• bundle-version - a version range to select the bundle version of the exporting bundle. The default
value is 0.0.0.
Packages may be named explicitly or by using wild-carded expressions such as org.foo.* and *. The
wildcard can stand for any suffix, including multiple sub-packages. If a wildcard is used, then the
package identified by the prefix must not be included. That is, org.foo.* will include all sub-pack-
ages of org.foo but it must not include package org.foo itself.
Dynamic imports must be searched in the order in which they are specified. The order is particular-
ly important when package names with wildcards are used. The order will then determine the order
in which matching occurs. This means that the more specific package specifications should appear
before the broader specifications. For example, the following DynamicImport-Package header indi-
cates a preference for packages supplied by ACME:
DynamicImport-Package: *;vendor=acme, *
If multiple packages need to be dynamically imported with identical parameters, the syntax permits
a list of packages, separated by semicolons, to be specified before the parameters.
During class loading, the package of the class being loaded is compared against the specified list
of (possibly wild-carded) package names. Each matching package name is used in turn to attempt
to wire to an export using the same rules as Import-Package. If a wiring attempt is successful (tak-
ing any uses constraints into account), the search is forwarded to the exporter's class loader where
class loading continues. The wiring must not subsequently be modified, even if the class cannot be
loaded. This implies that once a package is dynamically resolved, subsequent attempts to load class-
es or resources from that package are treated as normal imports.
In order for a DynamicImport-Package to be resolved to an export statement, all attributes of the dy-
namic import definition must match the attributes of the export statement. All mandatory arbitrary
attributes (as specified by the exporter, see Mandatory Attributes on page 63 ) must be specified in
the dynamic import definition and match.
Once a wire is established, any uses constraints from the exporter must be obeyed for further dy-
namic imports.
Dynamic imports are very similar to optional packages, see Optional Packages on page 60, but dif-
fer in the fact that they are handled after the bundle is resolved.
org.osgi.framework.bootdelegation
The .* wildcard means deep matching, that is, com.acme.*, matches any sub-package of package
com.acme, however, it does not match com.acme. Packages that match this list must be loaded from
the parent class loader. The java.* prefix is always implied; it does not have to be specified.
The single wildcard means that the Framework must always delegate to the parent class loader first,
which is the same as the Release 3 behavior. For example, when running on an Oracle JVM, it may
be necessary to specify a value like:
org.osgi.framework.bootdelegation=sun.*,com.sun.*
With such a property value, the Framework must delegate all java.*, sun.*, and com.sun.* packages
to the parent class loader.
1. If the class or resource is in a java.* package, the request is delegated to the parent class loader;
otherwise, the search continues with the next step. If the request is delegated to the parent class
loader and the class or resource is not found, then the search terminates and the request fails.
2. If the class or resource is from a package included in the boot delegation list
(org.osgi.framework.bootdelegation), then the request is delegated to the parent class loader. If
the class or resource is found there, the search ends.
3. If the class or resource is in a package that is imported using Import-Package or was imported
dynamically in a previous load, then the request is delegated to the exporting bundle's class
loader; otherwise the search continues with the next step. If the request is delegated to an ex-
porting class loader and the class or resource is not found, then the search terminates and the re-
quest fails.
4. If the class or resource is in a package that is imported from one or more other bundles using Re-
quire-Bundle, the request is delegated to the class loaders of the other bundles, in the order in
which they are specified in this bundle's manifest. This entails a depth-first strategy; all required
bundles are searched before the bundle class path is used. If the class or resource is not found,
then the search continues with the next step.
5. Search the bundle's embedded class path, see Bundle Class Path on page 67. If the class or re-
source is not found, then continue with the next step.
6. If the class or resource is in a package that is exported by the bundle or the package is imported
by the bundle (using Import-Package or Require-Bundle), then the search ends and the class or
resource is not found.
7. Otherwise, if the class or resource is in a package that is imported using DynamicImport-Pack-
age, then a dynamic import of the package is now attempted. An exporter must conform to any
implied package constraints. If an appropriate exporter is found, a wire is established so that fu-
ture loads of the package are handled in step 3. If a dynamic wire is not established, then the re-
quest fails.
8. If the dynamic import of the package is established, the request is delegated to the exporting
bundle's class loader. If the request is delegated to an exporting class loader and the class or re-
source is not found, then the search terminates and the request fails.
When delegating to another bundle class loader, the delegated request enters this algorithm at step
4.
The following non-normative flow chart illustrates the search order described above:
Start
no
no
no
no
Failure
Search bundle yes
5 found?
class path Success
no
package yes
7
exported?
no
no no
org.osgi.framework.system.packages
contains the export packages descriptions for the system bundle. This property employs the stan-
dard Export-Package manifest header syntax:
Some classes on the boot class path assume that they can use any class loader to load other class-
es on the boot class path, which is not true for a bundle class loader. Framework implementations
should attempt to load these classes from the boot class path.
The system bundle (bundle ID zero) is used to export non-java.* packages from the parent class
loader. Export definitions from the system bundle are treated like normal exports, meaning that
they can have version numbers, and are used to resolve import definitions as part of the normal
bundle resolving process. Other bundles may provide alternative implementations of the same
packages.
The set of export definitions for the parent class loader can either be set by this property or calcu-
lated by the Framework. The export definitions must have the bundle-symbolic-name and bun-
dle-version attributes with the implementation-specific bundle symbolic name and bundle version
value of the system bundle.
Exposing packages from the parent class loader in this fashion must also take into account any uses
directives of the underlying packages. For example, the definition of javax.crypto.spec must declare
its usage of javax.crypto.interfaces and javax.crypto.
• Bundle entry URLs must be hierarchical (See [13] RFC 2396 Uniform Resource Identifiers URI: Gener-
ic Syntax )
• Usable as a context for constructing another URL.
• The java.net.URLStreamHandler class used for a bundle entry URL must be available to the
java.net.URL class to setup a URL that uses the protocol scheme defined by the Framework.
• The getPath method for a bundle entry URL must return an absolute path (a path that starts with
'/') to a resource or entry in a bundle. For example, the URL returned from getEntry("myimages/
test.gif ") must have a path of /myimages/test.gif.
For example, a class can take a URL to an index.html bundle resource and map URLs in this resource
to other files in the same JAR directory.
A: Require-Bundle: B, C
C: Require-Bundle: D
A p
B p p C
D
p
Each of the bundles exports the package p. In this example, bundle A requires bundle B, and bun-
dle C requires bundle D. When bundle A loads a class or resource from package p, then the required
bundle search order is the following: B, D, C, A. This is a depth first search order because required
bundles are searched before the bundle class path is searched (see step 4 ). The required bundles are
searched in the order that they appear in the Require-Bundle header. The depth first search order can
introduce endless search cycles if the dependency graph has a cycle in it.
Using the previous setup, a cycle can be introduced if bundle D requires bundle A as depicted in Fig-
ure 3.16.
D: Require-Bundle: A
A p
B p p C
D
p
When the class loader for bundle A loads a class or resource from package p then the bundle search
order would be the following: B, B, B,... if cycles were not taken into account.
Since a cycle was introduced each time bundle D is reached the search will recurs back to A and
start over. The framework must prevent such dependency cycles from causing endless recursive
lookups.
To avoid endless looping, the Framework must mark each bundle upon first visiting it and not ex-
plore the required bundles of a previously visited bundle. Using the visited pattern on the depen-
dency graph above will result in the following bundle search order: B, D, C, A.
• Framework Util - Through the FrameworkUtil class with the getBundle(Class) method. The frame-
work provides this method to allow code to find the bundle of an object without having the per-
mission to get the class loader. The method returns null when the class does not originate from a
bundle.
• Class Loader - An OSGi framework must ensure that the class loader of a class that comes from
a bundle implements the BundleReference interface. This allows legacy code to find an object's
bundle by getting its class loader and casting it to a BundleReference object, which provides ac-
cess to the Bundle. However, this requires the code to have the permission to access the class
loader. The following code fragment shows how to obtain a Bundle object from any object.
ClassLoader cl = target.getClassLoader();
if ( cl instanceof BundleReference ) {
BundleReference ref = (BundleReference) cl;
Bundle b = ref.getBundle();
...
}
In an OSGi system, not all objects belong to the framework. It is therefore possible to get hold of a
class loader that does not implement the BundleReference interface, for example the boot class path
loader.
When locating a path in a bundle the Framework must attempt to locate the path relative to the
root of the bundle that contains the corresponding native code clause in its manifest header.
The following attributes are architected:
• osname - Name of the operating system. The value of this attribute must be the name of the op-
erating system upon which the native libraries run. A number of canonical names are defined in
Table 4.3.
• osversion - The operating system version. The value of this attribute must be a version range as
defined in Version Ranges on page 39.
• processor - The processor architecture. The value of this attribute must be the name of the
processor architecture upon which the native libraries run. A number of canonical names are de-
fined in Table 4.2.
• language - The ISO code for a language. The value of this attribute must be the name of the lan-
guage for which the native libraries have been localized.
• selection-filter - A selection filter. The value of this attribute must be a filter expression that in-
dicates if the native code clause should be selected or not.
If a selection-filter attribute contains an invalid filter, then the bundle must fail to install with a
Bundle Exception of type NATIVECODE_ERROR. The following is a typical example of a native code
declaration in a bundle's manifest:
osname = Windows98 ; «
osname = WindowsNT ; «
processor = x86 ; «
selection-filter = «
"(com.acme.windowing=win32)"; «
language = en ; «
language = se , «
lib/solaris/libhttp.so ; «
osname = Solaris ; «
osname = SunOS ; «
processor = sparc, «
lib/linux/libhttp.so ; «
osname = Linux ; «
processor = mips; «
selection-filter = «
"(com.acme.windowing=gtk)"
If multiple native code libraries need to be installed on one platform, they must all be specified in
the same clause for that platform.
If a Bundle-NativeCode clause contains duplicate parameter entries, the corresponding values must
be OR'ed together. This feature must be carefully used because the result is not always obvious. This
is highlighted by the following example:
The above example implies that the native library will load on Windows XP 3.1 and later, which was
probably not intended. The single clause should be split in two clauses:
Bundle-NativeCode: lib/http.DLL ; «
osname = Windows95 ; «
osversion = 3.1; «
processor = x86, «
lib/http.DLL ; «
osname = WindowsXP ; «
osversion = 5.1; «
processor = x86
Any paths specified in the matching clause must be present in the bundle or any of its attached
fragments for a bundle to resolve. The framework must report a Bundle Exception with the
NATIVECODE_ERROR as error code when the bundle can not be resolved due to a native code prob-
lem.
If the optional '*' is specified at the end of the Bundle-NativeCode manifest header, the bundle will
still resolve even if the Bundle-NativeCode header has no matching clauses.
The following is a typical example of a native code declaration in a bundle's manifest with an op-
tional clause:
Bundle-NativeCode: lib/win32/winxp/optimized.dll; «
lib/win32/native.dll ; «
osname = WindowsXP ; «
processor = x86 , «
lib/win32/native.dll ; «
osname = Windows95 ; «
osname = Windows98 ; «
osname = WindowsNT ; «
osname = Windows2000; «
processor = x86 , «
*
• osgi.native.osname - Uses the approximate equals (~=) filter type to evaluate the value specified
by the osname Bundle-NativeCode attribute.
• osgi.native.osversion - Create a VersionRange using the value specified by the osversion Bun-
dle-NativeCode attribute and then create a filter string out of the VersionRange.
• osgi.native.processor - Uses the approximate equals (~=) filter type to evaluate the value speci-
fied by the processor Bundle-NativeCode attribute.
• osgi.native.language - Uses the approximate equals (~=) filter type to evaluate the value specified
by the language Bundle-NativeCode attribute.
In cases where the same Bundle-NativeCode attribute is specified multiple times within the same
clause then the filter components for each value for that attribute are ORed together. For example,
if osname attribute is specified as both "Windows95" and "Windows7" then the resulting filter will
contain:
(|
(osgi.native.osname~=Windows95)
(osgi.native.osname~=Windows7)
)
If the selection-filter Bundle-NativeCode attribute is specified then the specified filter is included as
a component of the native code clauses AND filter type. Consider the following Bundle-NativeCode
header which contains a single clause:
Bundle-NativeCode: «
lib/http.dll; lib/zlib.dll; «
osname=Windows95; «
osname=Windows98; «
osname=WindowsNT; «
processor=x86; «
selection-filter="(com.acme.windowing=win32)"; «
language=en; «
language=se
This clause would get translated into the following AND filter type:
Require-Capability: «
osgi.native; «
filter:=" «
(& «
(| «
(osgi.native.osname~=Windows95) «
(osgi.native.osname~=Windows98) «
(osgi.native.osname~=WindowsNT) «
) «
(osgi.native.processor~=x86) «
(| «
(osgi.native.language~=en) «
(osgi.native.language~=se) «
) «
(com.acme.windowing=win32) «
)"
The Bundle-NativeCode header may specify multiple clauses, each having their own list of native
code paths and set of matching attributes. Instead of using a separate osgi.native requirement for
each Bundle-NativeCode clause, the complete Bundle-NativeCode header is specified as a single
osgi.native requirement. This is done by using an OR filter type using all of the individual Bun-
dle-NativeCode clause filter components (as specified above) as components of a single filter direc-
tive. Consider the following Bundle-NativeCode header which contains three clauses:
Bundle-NativeCode: «
lib/http.dll; lib/zlib.dll; «
osname=Windows95; «
osname=Windows98; «
osname=WindowsNT; «
processor=x86; «
selection-filter = "(com.acme.windowing=win32)"; «
language=en; «
language=se, «
lib/solaris/libhttp.so; «
osname=Solaris; «
osname=SunOS; «
processor=sparc, «
lib/linux/libhttp.so; «
osname=Linux; «
processor=mips; «
selection-filter="(com.acme.windowing=gtk)"
This Bundle-NativeCode header would get translated into the following osgi.native filter directive:
(|
(&
(|
(osgi.native.osname~=Windows95)
(osgi.native.osname~=Windows98)
(osgi.native.osname~=WindowsNT)
)
(osgi.native.processor~=x86)
(|
(osgi.native.language~=en)
(osgi.native.language~=se)
)
(com.acme.windowing=win32)
)
(&
(|
(osgi.native.osname~=Solaris)
(osgi.native.osname~=SunOs)
)
(osgi.native.processor~=sparc)
)
(&
(osgi.native.osname~=Linux)
(osgi.native.processor~=mips)
(com.acme.windowing=gtk)
)
)
If the optional '*' is specified at the end of the Bundle-NativeCode manifest header, then the native
code for the bundle is considered to be optional. When the Framework converts a Bundle-Native-
Code header into an osgi.native requirement which is designated as optional then the requirement
resolution directive must be set to optional
1. Only select the native code clauses for which the following expressions all evaluate to true.
• osname ~= [org.osgi.framework.os.name] or osname is not specified
• processor ~= [org.osgi.framework.processor] or processor is not specified
• osversion range includes [org.osgi.framework.os.version] or osversion is not specified
• language ~= [org.osgi.framework.language] or language is not specified
• selection-filter evaluates to true when using the values of the launching properties or selec-
tion-filter is not specified
2. If no native clauses were selected in step 1, this algorithm is terminated. A Bundle Exception is
thrown if the optional clause is not present.
3. The selected clauses are now sorted in the following priority order:
• osversion: floor of the osversion range in descending order, osversion not specified
• language: language specified, language not specified
• Position in the Bundle-NativeCode manifest header: lexical left to right.
4. The first clause of the sorted clauses from step 3 must be used as the selected native code clause.
If a native code library in a selected native code clause cannot be found within the bundle then the
bundle is still allowed to resolve. A missing native code library will result in an error being thrown
at runtime when the bundle attempts to load the native code (for example, by invoking the method
System.loadLibrary).
If the selected clause contains multiple libraries with the same base file name then only the lexi-
cally left most library with that base file name will be used. For example, if the selected clause con-
tains the libraries lib1/http.dll; lib2/http.dll; lib3/foo.dll; a/b/c/http.dll then only http.dll in lib1
and foo.dll will be used.
Designing a bundle native code header can become quickly complicated when different operating
systems, libraries, and languages are used. The best practice for designing the header is to place all
parameters in a table. Every targeted environment is then a row in that table. See Table 3.2 for an ex-
ample.
processor
osversion
language
osname
filter
Libraries
nativecodewin32.dll, delta.dll win32 x86 en
nativecodegtk.so linux x86 en (com.acme.windowing=gtk)
nativecodeqt.so linux x86 en (com.acme.windowing=qt)
This table makes it easier to detect missing combinations. This table is then mapped to the Bun-
dle-NativeCode header in the following code example.
Bundle-NativeCode: nativecodewin32.dll; «
delta.dll; «
osname=win32; «
processor=x86; «
language=en, «
nativecodegtk.so; «
osname=linux; «
processor=x86; «
language=en; «
selection-filter= «
"(com.acme.windowing=gtk)", «
nativecodeqt.so; «
osname=linux; «
processor=x86; «
language=en; «
selection-filter = «
"(com.acme.windowing=qt)"
3.11 Localization
A bundle contains a significant amount of information that is human-readable. Some of this infor-
mation may require different translations depending on the user's language, country, and any spe-
cial variant preferences, a.k.a. the locale. This section describes how a bundle can provide common
translations for the manifest and other configuration resources depending on a locale.
Bundle localization entries share a common base name. To find a potential localization entry, an un-
derscore ('_' \u005F) is added plus a number of suffixes, separated by another underscore, and final-
ly appended with the suffix .properties . The suffixes are defined in java.util.Locale. The order for
the suffixes this must be:
• language
• country
• variant
For example, the following files provide manifest translations for English, Dutch (Belgium and the
Netherlands) and Swedish.
OSGI-INF/l10n/bundle_en.properties
OSGI-INF/l10n/bundle_nl_BE.properties
OSGI-INF/l10n/bundle_nl_NL.properties
OSGI-INF/l10n/bundle_sv.properties
The Framework searches for localization entries by appending suffixes to the localization base
name according to a specified locale and finally appending the .properties suffix. If a translation is
not found, the locale must be made more generic by first removing the variant, then the country
and finally the language until an entry is found that contains a valid translation. For example, look-
ing up a translation for the locale en_GB_welsh will search in the following order:
OSGI-INF/l10n/bundle_en_GB_welsh.properties
OSGI-INF/l10n/bundle_en_GB.properties
OSGI-INF/l10n/bundle_en.properties
OSGI-INF/l10n/bundle.properties
This allows localization files for more specific locales to override localizations from less specific lo-
calization files.
• fragment bundle - If the bundle is a resolved fragment, then the search for localization data must
delegate to the attached host bundle with the highest version. If the fragment is not resolved,
then the framework must search the fragment's JAR for the localization entry.
• other bundle - The framework must first search in the bundle's JAR for the localization entry. If
the entry is not found and the bundle has fragments, then the attached fragment JARs must be
searched for the localization entry.
The bundle's class loader is not used to search for localization entries. Only the contents of the bun-
dle and its attached fragments are searched. The bundle will still be searched for localization entries
even if the full stop ('.' \u002E) is not in the bundle class path.
User-defined headers can also be localized. Spaces in the localization keys are explicitly allowed.
The previous example manifest entries could be localized by the following entries in the manifest
localization entry OSGI-INF/l10n/bundle.properties.
# bundle.properties
acme\ bundle=The ACME Bundle
acme\ corporation=The ACME Corporation
acme\ description=The ACME Bundle provides all of the ACME\ services
acme\ special\ header=user-defined Acme Data
The above manifest entries could also have French localizations in the manifest localization entry
OSGI-INF/l10n/bundle_fr_FR.properties.
• Missing Bundle-SymbolicName.
• Duplicate attribute or duplicate directive (except in the Bundle-Native code clause).
• Multiple imports of a given package.
• Export of java.* packages.
• Export-Package, Bundle-SymbolicName, or Fragment-Host with a mandatory attribute that is not
defined.
• Installing or updating a bundle to a bundle that has the same symbolic name and version as an-
other installed bundle (unless this is allowed, see Bundle Identifiers on page 113).
• Any syntactic error (for example, improperly formatted version or bundle symbolic name, unrec-
ognized directive value, etc.).
• Specification-version and version specified together (for the same package(s)) but with different
values on manifest headers that treat them as synonyms. For example:
Import-Package p;specification-version=1;version=2
Import-Package p;specification-version=1,q;version=2
3.13.1 Require-Bundle
The Require-Bundle manifest header contains a list of required bundle symbolic names, with op-
tional attribute assertions. These bundles are searched after the imports are searched but before the
bundle's class path is searched. Fragment or extension bundles cannot be required.
The framework must take all exported packages from a required bundle, including any packages ex-
ported by attached fragments, and wire these packages to the requiring bundle.
The Require-Bundle manifest header must conform to the following syntax:
• visibility - If the value is private (default), then all visible packages from the required bundles
are not re-exported. If the value is reexport then bundles that require this bundle will transitive-
ly have access to these required bundle's exported packages. That is, if bundle A requires bundle
B, and bundle B requires bundle C with visibility:=reexport then bundle A will have access to all
bundle C's exported packages as if bundle A had required bundle C.
• resolution - If the value is mandatory (default) then the required bundle must exist for this bun-
dle to resolve. If the value is optional, the bundle will resolve even if the required bundle does
not exist.
• bundle-version - The value of this attribute is a version range to select the bundle version of the
required bundle. See Version Ranges on page 39. The default value is [0.0.0,∞).
The Bundle-SymbolicName header can specify further arbitrary attributes that must be matched be-
fore a bundle is eligible.
A specific symbolic name can only be required once, listing the same symbolic name multiple times
must be regarded as an install error.
Requiring bundles must get wired to all exported packages of all their required bundles including
exported packages from their attached fragments. This means that any mandatory attributes on
these exports must be ignored. However, if a required bundle's exported package is substituted for
an imported package, then the requiring bundles must get wired to the same exported package that
the required bundle is wired to ensure class space consistency.
For example, assume that bundle A exports and imports package p and bundle B requires bundle A:
Bundle A
Export-Package: p;x=1;mandatory:=x
Import-Package: p
Bundle B
Require-Bundle: A
In this constellation, bundle B will get package p from the same source as bundle A. Bundle A can
get the package from itself if it is chosen as an exporter for p, but it can also get the package from an-
other bundle because it also imports it. In all cases, bundle B must use exactly the same exporter for
package p as bundle A.
A given package may be available from more than one of the required bundles. Such packages are
named split packages because they derive their contents from different bundles. If these different
bundles provide the same classes unpredictable shadowing of classes can arise, see Issues With Re-
quiring Bundles on page 86. However, split packages without shadowing are explicitly permitted.
For example, take the following setup:
A: Require-Bundle: B
Export-Package: p
B: Export-Package: p;partial=true;mandatory:=partial
If bundle C imports package p, it will be wired to package A.p, however the contents will come from
B.p > A.p. The mandatory attribute on bundle B's export definition ensures that bundle B is not ac-
cidentally selected as exporter for package p. Split packages have a number drawbacks that are dis-
cussed in Issues With Requiring Bundles on page 86.
Resources and classes from a split package must be searched in the order in which the required bun-
dles are specified in the Require-Bundle header.
As an example, assume that a bundle requires a number of required bundles and a number of lan-
guage resources (also bundles) that are optional.
Require-Bundle: com.acme.facade;visibility:=reexport, «
com.acme.bar.one;visibility:=reexport, «
com.acme.bar.two;visibility:=reexport, «
com.acme.bar._nl;visibility:=reexport;resolution:=optional, «
com.acme.bar._en;visibility:=reexport;resolution:=optional
A bundle may both import packages (via Import-Package) and require one or more bundles (via Re-
quire-Bundle), but if a package is imported via Import-Package, it is not also visible via Require-Bun-
dle: Import-Package takes priority over Require-Bundle, and packages which are exported by a re-
quired bundle and imported via Import-Package must not be treated as split packages.
In order to be allowed to require a named bundle, the requiring bundle must have
BundlePermission[<bundle symbolic name>, REQUIRE], where the bundle symbolic name is the
name of the bundle that is required. The required bundle must be able to provide the bundle and
must therefore have BundlePermission[<bundle symbolic name>, PROVIDE], where the name des-
ignates the requiring bundle. In the case a fragment bundle requires another bundle, the Bundle Per-
mission must be checked against the fragment bundle's Protection Domain.
• Split Packages - Classes from the same package can come from different bundles with Require
bundle, such a package is called a split package. Split packages have the following drawbacks:
• Completeness - Split packages are open ended, it is difficult to guarantee that all the intended
pieces of a split package have actually been included.
• Ordering - If the same classes are present in more than one required bundle, then the ordering
of Require-Bundle is significant. A wrong ordering can cause hard to trace errors, similar to
the traditional class path model of Java.
• Performance - A class must be searched in all providers when packages are split. This potential-
ly increases the number of times that a ClassNotFoundException must be thrown which can
potentially introduce a significant overhead.
• Confusing - It is easy to find a setup where there is lots of potential for confusion. For example,
the following setup is non-intuitive.
A: Export-Package: p;uses:=q
Import-Package: q
B: Export-Package: q
C: Export-Package: q
D: Require-Bundle: B, C
Import-Package: p
A B
q q
p
Potential
1 conflict
D p q C
2
In this example, bundle D merges the split package q from bundles B and bundle C, however, im-
porting package p from bundle A puts a uses constraint on package p for package q. This implies
that bundle D can see the valid package q from bundle B but also the invalid package q from bun-
dle C. This wiring is allowed because in almost all cases there will be no problem. However, the
consistency can be violated in the rare case when package C.q contains classes that are also in
package B.q.
• Mutable Exports - The feature of visibility:=reexport that the export signature of the requiring
bundle can unexpectedly change depending on the export signature of the required bundle.
• Shadowing - The classes in the requiring bundle that are shadowed by those in a required bundle
depend on the export signature of the required bundle and the classes the required bundle con-
tains. (By contrast, Import-Package, except with resolution:=optional, shadows whole packages
regardless of the exporter.)
1. Append the import definitions for the Fragment bundle that do not conflict with an import def-
inition of the host to the import definitions of the host bundle. A Fragment can provide an im-
port statement for a private package of the host. The private package in the host is hidden in
that case.
2. Append the Require-Bundle entries of the fragment bundle that do not conflict with a Re-
quire-Bundle entry of the host to the Require-Bundle entries of the host bundle.
3. Append the export definitions of a Fragment bundle to the export definitions of the host bundle
unless the exact definition (directives and attributes must match) is already present in the host.
Fragment bundles can therefore add additional exports for the same package name. The bun-
dle-version attributes and bundle-symbolic-name attributes will reflect the host bundle.
4. Append the Provide-Capability clauses of the fragment to the Provide-Capability clauses of the
host
5. Append the Require-Capability clauses of the fragment to the Require-Capability clauses of the
host
A host and a fragment conflict when they cannot resolve to provide a consistent class space. If a con-
flict is found, the Fragment bundle is not attached to the host bundle.
A Fragment bundle must enter the resolved state only if it has been successfully attached to at least
one host bundle.
During runtime, the fragment's JAR is searched after the host's bundle class path as described in
Fragments During Runtime on page 88.
A Fragment bundle can not be required by another bundle with the Require-Bundle header.
3.14.1 Fragment-Host
The Fragment-Host manifest header links the fragment to its potential hosts. It must conform to the
following syntax:
• extension - Indicates this extension is a system or boot class path extension. It is only applica-
ble when the Fragment-Host is the System Bundle. This is discussed in Extension Bundles on page
90. The following values are supported:
• framework - The fragment bundle is a Framework extension bundle (default).
• bootclasspath - The fragment bundle is a boot class path extension bundle.
The fragment must be the bundle symbolic name of the implementation specific system bundle
or the alias system.bundle. The Framework should fail to install an extension bundle when the
bundle symbolic name is not referring to the system bundle.
• bundle-version - The version range to select the host bundle. If a range is used, then the frag-
ment can attach to multiple hosts. See Semantic Versioning on page 58. The default value is
[0.0.0,∞).
The Fragment-Host header can assert arbitrary attributes that must be matched before a host is eligi-
ble.
When a fragment bundle is attached to a host bundle, it logically becomes part of it. All classes and
resources within the fragment bundle must be loaded using the class loader (or Bunde object) of its
host bundle. The fragment bundles of a host bundle must be attached to a host bundle in the order
that the fragment bundles are installed, which is in ascending bundle ID order. If an error occurs
during the attachment of a fragment bundle then the fragment bundle must not be attached to the
host. A fragment bundle must enter the resolved state only if it has been successfully attached to
one or more host bundles.
In order for a host bundle to allow fragments to attach, the host bundle must have
BundlePermission[<bundle symbolic name>,HOST]. In order to be allowed to attach to a host bun-
dle, a fragment bundle must have BundlePermission[<bundle symbolic name>,FRAGMENT].
Though a fragment bundle does not have its own class loader, it still must have a separate Protection
Domain when it is not an extension fragment. Each fragment can have its own permissions linked
to the fragment bundle's location and signer.
A host bundle's class path is searched before a fragment's class path. This implies that packages can
be split over the host and any of its fragments. Searching the fragments must be done in ascending
bundle ID order. This is the order that the fragment bundles were installed.
Figure 3.18 Resource/class searching with fragments
A.p export is chosen
A p
p D p
q q
q
r
1 2
B p C q
r s
t t
Figure 3.18 shows a setup with two fragments. Bundle B is installed before bundle C and both bundle
B and bundle C attach to bundle A. The following table shows where different packages originate in
this setup. Note that the order of the append (>) is significant.
Table 3.3 Effect of fragments on searching
Package Requested From Remark
p A.p > B.p Bundle A exports package p, therefore, it will search its
class path for p. This class path consists of the JAR and
then its Fragment bundles.
q D.q The import does not handle split packages and pack-
age q is imported from bundle D. Therefore, C.q is not
found.
r A.r > B.r Package r is not imported and therefore comes from
the class path.
s C.s
t B.t > C.t
In the example above, if package p had been imported from bundle D, the table would have looked
quite different. Package p would have come from bundle D, and bundle A's own contents as well as
the contents of bundle B would have been ignored.
If package q had bundle D, then the class path would have to be searched, and A.q would have con-
sisted of A.q > C.q.
Fragments must remain attached to a host as long as the host remains resolved. When a host bundle
becomes unresolved, then all its attached Fragment bundles must be detached from the host bundle.
When a fragment bundle becomes unresolved the Framework must:
• Bundle-Activator
Fragment-Host: system.bundle
The following example uses the Fragment-Host manifest header to specify an extension bundle for a
specific Framework implementation.
Fragment-Host: com.acme.impl.framework
It is valid to update an extension bundle to a bundle of another type. If the old extension bundle is
resolved then it must be attached as a fragment to the system bundle. When this bundle is updat-
ed the old content of the bundle must remain attached to the system bundle until the system bun-
dle is refreshed or the extension bundle is refreshed (using the Wiring API). This must initiate and
Framework shutdown and restart. When the framework comes back up the new content of the bun-
dle may be resolved.
All Bundle events should be dispatched for extension bundles as for ordinary bundles.
• Require-Bundle
• Bundle-NativeCode
• DynamicImport-Package
• Bundle-Activator
Extension bundles are permitted to specify an Export-Package header. Any exported packages spec-
ified by an extension bundle must be hosted (exported) by the System Bundle when the extension
bundle is resolved.
Extension bundles are permitted to specify Import-Package and Require-Capability headers to de-
clare dependencies on packages and capabilities.
ExtensionBundle-Activator: com.acme.Activator
The class acting as an Extension Bundle Activator must implement the BundleActivator interface,
be declared public, and have a public default constructor so an instance of it may be created with
Class.newInstance.
Supplying an Extension Bundle Activator is optional and only valid for Extension Bundles. For nor-
mal Bundles and Fragments, the ExtensionBundle-Activator must be ignored.
work on page 110 describes how the stop method for Extension Bundle Activators is called during
Framework shutdown.
3.15.4.2 Installing
When an extension bundle is installed, a Framework must allow the extension to become resolved
dynamically, without a Framework restart. When an extension bundle is resolved dynamically after
Framework initialization, then the Extension Bundle Activator start method must be called as soon
as the extension bundle is resolved. This must happen before the Bundle Event of type RESOLVED is
fired for the extension bundle.
• org.osgi.supports.framework.requirebundle
• org.osgi.supports.framework.fragments
• org.osgi.supports.framework.extension
3.16 Security
3.16.1 Extension Bundles
In an environment that has Java security enabled the Framework must perform an additional secu-
rity check before allowing an extension bundle to be installed. In order for an extension bundle to
successfully install, the Framework must check that the extension bundle has All Permissions as-
signed to it. This means that the permissions of an extension bundle must be setup before the exten-
sion bundle is installed.
AllPermission must be granted to extension bundles because they will be loaded under the Protec-
tion Domain of either the boot class path or the Framework implementation. Both of these Protec-
tion Domains have All Permissions granted to them. Attempting to install an extension bundle that
has not already been granted All Permissions must result in a Bundle Exception.
The installer of an extension bundle must have AdminPermission[<extension
bundle>,EXTENSIONLIFECYCLE] to install an extension bundle.
When a fragment contains a Require-Bundle header, the Framework must check the permission
against the domain of the fragment.
• The name, either the name of the target package (with a possible wildcard character at the end)
or a filter expression that can verify the exporting bundle. A filter expression can test for the
package name with the package.name key. A filter can only be used for an IMPORT action. Filters
are described in Filter Based Permissions on page 29.
• The action, either IMPORT or EXPORTONLY.
For example, the following Package Permission permits to import any package from a bundle down-
loaded from ACME:
PackagePermission("(location=http://www.acme.com/*",IMPORT)
When a fragment adds imports and exports to the host, the framework must check the protection
domain of the fragment and not of the related host.
• Itself
• Any attached fragments
• Any resources from imported packages
A resource in a bundle may also be accessed by using certain methods on Bundle. The caller of these
methods must have AdminPermission[bundle, RESOURCE].
If the caller does not have the necessary permission, a resource is not accessible and null must be re-
turned. Otherwise, a URL object to the resource must be returned. These URLs are called bundle re-
source URLs. Once the URL object is returned, no further permission checks are performed when the
contents of the resource are accessed. The URL object must use a scheme defined by the Framework
implementation.
Bundle resource URLs are normally created by the Framework, however, in certain cases bundles
need to manipulate the URL to find related resources. For example, a URL can be constructed to a re-
source that is in the same directory as a given resource.
URLs that are not constructed by the Framework must follow slightly different security rules due
to the design of the java.net.URL class. Not all constructors of the URL class interact with the URL
Stream Handler classes (the implementation specific part). Other constructors call at least the
parseURL method in the URL Stream Handler where the security check can take place. This design
makes it impossible for the Framework check the permissions during construction of a bundle re-
source URL.
The following constructors use the parseURL method and are therefore checked when a bundle re-
source URL is constructed.
URL(String spec)
URL(URL context, String spec)
URL(URL context, String spec, URLStreamHandler handler)
When one of these constructors is called for a bundle resource URL, the implementation of the
Framework must check the caller for the necessary permissions in the parseURL method. If the
caller does not have the necessary permissions then the parseURL method must throw a Securi-
ty Exception. This will cause a Malformed URL Exception to be thrown by the URL constructor. If
the caller has the necessary permissions, then the URL object is setup to access the bundle resource
without further checks.
The following java.net.URL constructors do not call the parseURL method in the URL Stream Han-
dler, making it impossible for the Framework to verify the permission during construction.
Bundle resource URLs that are created with these constructors cannot perform the permission
check during creation and must therefore delay the permission check. When the content of
the URL is accessed, the Framework must throw a Security Exception if the caller does not have
AdminPermission[bundle, RESOURCE] for the bundle referenced by the URL.
The filter can also assert information from the target bundle. The target bundle is always the bundle
that provides the capability. This means that a requirer can be restricted to receive a capability from
a specific bundle.
Capabilities in a namespace for which the resolving bundle has no permission are not available to
other bundles. Requirements in a namespace for which a bundle has no permission can never be sat-
isfied.
The Capability Permission has the following actions:
• REQUIRE - Imply permission to require the given namespace. The target bundle that can be as-
serted in the filter is the bundle providing the capability.
• PROVIDE - Imply permission to provide a capability in the given namespace, the target bundle is
the bundle that is checked for the permission.
This class of this Permission instance comes from a particular source. Permissions can only be tested
against instances that come from the same source.
Therefore, the Framework needs to look up permissions based on class rather than class name. When
it needs to instantiate a permission it must use the class of the permission being checked to do the
instantiation. This is a complication for Framework implementers; bundle programmers are not af-
fected.
Consider the following example:
Bundle A
Import-Package: p
Export-Package: q
Bundle B
Import-Package: p
• Bundle A uses a p.FooService. Usage of this class checks q.FooPermission whenever one of its
methods is invoked.
• Bundle B has a FooPermission in its Protection Domain in a (Conditional) Permission Info object.
• Bundle B invokes a method in the FooService that was given by bundle A.
• The FooService calls the checkPermission method with a new FooPermission instance.
• The Framework must use a FooPermission object that is from the same class loader as the given
FooPermission object before it can call the implies method. In this case, the FooPermission class
comes from package A.q.
After the permission check, bundle B will have a FooPermission instantiated using a class from a
package it does not import. It is therefore possible that the Framework has to instantiate multiple
variations of the FooPermission class to satisfy the needs of different bundles.
3.17 References
[1] Java Virtual Machine Specification
https://docs.oracle.com/javase/specs/
[2] The Standard for the Format of ARPA Internet Text Messages
STD 11, RFC 822, UDEL, August 1982
http://www.ietf.org/rfc/rfc822.txt
[3] The Hypertext Transfer Protocol - HTTP/1.1
RFC 2068 DEC, MIT/LCS, UC Irvine, January 1997
http://www.ietf.org/rfc/rfc2068.txt
[4] Java Language Specification
https://docs.oracle.com/javase/specs/
3.18 Changes
• Updated Bundle-License: Apache-2.0; link="http://opensource.org/licenses/apache2.0.php" on page
35 to recommend using license identifiers from [25] Software Package Data Exchange (SPDX)
License List.
• Added Bundle-Developers: pkriens; [email protected]; name="Peter Kriens"; organization="OSGi
Alliance" on page 34 to hold information about the bundle's developers.
• Added Bundle-SCM: url=https://github.com/bndtools/bnd, connection=scm:git:https://github.com/bnd-
tools/bnd.git, developerConnection=scm:git:[email protected]:bndtools/bnd.git on page 37 to hold in-
formation about the bundle's software configuration management system.
• Updated to reference the new bundle annotations in org.osgi.annotation.bundle.
• Removed specification for bootclasspath extension bundles.
• Added FrameworkEvent type STOPPED_SYSTEM_REFRESHED.
• Allow extension bundles to specify package and capability requirements.
• Mandate support for dynamically resolving extension bundles.
• Added support for multi-release JARs. See Multi-release JAR on page 41.
• Bundles may now import java.* packages to ensure the Java platform provides the required ja-
va.* packages. See Execution Environment on page 48. Importing a java.* package only affects
bundle resolution and wiring. Classes in java.* packages are always loaded from the parent class
loader. See Parent Delegation on page 70.
4.1 Introduction
The Life Cycle Layer provides an API to control the security and life cycle operations of bundles. The
layer is based on the module and security layer.
4.1.1 Essentials
• Complete - The Life Cycle layer must implement an API that fully covers the installation, starting,
stopping, updating, uninstallation, and monitoring of bundles.
• Reflective - The API must provide full insight into the actual state of the Framework.
• Secure - It must be possible to use the API in a secure environment using fine-grained permis-
sions. However, security must be optional.
• Manageable - It must be possible to manage a OSGi framework remotely.
• Launching - It must be able to launch an implementation of a framework in a standardized way.
4.1.2 Entities
• Bundle - Represents an installed bundle in the Framework.
• Bundle Context - A bundle's execution context within the Framework. The Framework passes this
to a Bundle Activator when a bundle is started or stopped.
• Bundle Activator - An interface implemented by a class in a bundle that is used to start and stop
that bundle.
• Bundle Event - An event that signals a life cycle operation on a bundle. This event is received via a
(Synchronous) Bundle Listener.
• Framework Event - An event that signals an error or Framework state change. The event is re-
ceived via a Framework Listener.
• Bundle Listener - A listener to Bundle Events.
• Synchronous Bundle Listener - A listener to synchronously delivered Bundle Events.
• Framework Listener - A listener to Framework events.
• Bundle Exception - An Exception thrown when Framework operations fail.
• System Bundle - A bundle that represents the Framework.
• Framework - An interface implemented by an object that represents the actual framework. It al-
lows external management of a Framework.
• Framework Factory - An interface implemented by Framework providers that allows the creation
of a framework object.
implementation
class loaded by
code of bundle
activated with
1
<<interface>> <<interface>> Framework Impl <<class>>
Constants Framework Framework
Event
1 0..n 1
1
<<class>> Framework <<interface>>
Bundle Event Factory Impl Framework
Factory
4.2 Frameworks
This section outlines how a launcher can launch a framework implementation and then manage it,
regardless of the implementation type of the framework. This allows a launcher to embed an OSGi
framework without having to provide code that differs between different implementations.
• Service Provider Configuration model, see Java Service Provider Configuration Support on page
112,
The FrameworkFactory interface has a single method: newFramework(Map). The map provides the
sole configuration properties for the framework object. The result of this method is a framework ob-
ject, this object implements the Framework interface. The Framework interface extends the Bundle
interface and adds methods to handle the issues unique to launching a framework. The framework
object can be seen as the system bundle, though the framework object and the system bundle do not
have to be identical, implementations are allowed to implement them in different objects.
Before the framework object can be used, the launcher must first initialize it by calling the init
method. After initialization, the framework object can provide a valid Bundle Context and has
registered any framework services, but any installed bundles must be in the INSTALLED state. The
launcher can then configure the framework object by installing bundles, interacting with the frame-
work services, or registering launcher services. The launcher can also start bundles, but these bun-
dles will not be started until the framework object becomes ACTIVE.
After the framework object is properly configured, the launcher can start it by calling the start
method. The framework object will become ACTIVE, and it will move the startlevel (if present) to
the configured start level. This can then resolve and start any installed bundle. After a framework
has become ACTIVE, it can be stopped from the framework object, or through the system bundle.
The launcher can wait for a framework object to be stopped with the waitForStop method. This
method will block until the framework is completely stopped and return a Framework event indi-
cating the cause of the stop. After the framework object has been shutdown, and the waitForStop
method has returned, all installed bundles will be in the INSTALLED state. The same framework ob-
ject can be re-initialized, and started again, any number of times.
The action diagram in Figure 4.2 shows a typical session. A new framework is created and initial-
ized. The launcher then gets the Bundle Context, installs a bundle and starts the framework. It then
gets a service, calls a method and then waits for the framework to stop. The service waits some time
and calls stop on the System Bundle. The dotted lines indicate some non-specified interactions that
are implementation dependent.
getBundleContext
installBundle
start
getServiceReference
getService
foo()
waitForStop
stop
If security is enabled, then the launcher and the framework require All Permission. If All Permission
is not available, then the framework must throw a Security Exception.
The following code shows how a framework can be launched.
FrameworkFactory factory =
(FrameworkFactory) Class.forName( factoryName )
.newInstance();
Framework framework = factory.newFramework(p);
framework.init();
framework.start();
framework.waitForStop(0);
}
• boot - The boot class loader of the VM. This is the default.
• app - The application class loader
• ext - The extension class loader
• framework - The class loader of the framework
org.osgi.framework.« Specifies an optional OS specific command to set file permis-
sions on a bundle's native code. This is required on some oper-
command.execpermission
ating systems to use native libraries. For example, on a UNIX
style OS you could have the following value:
org.osgi.framework.command.execpermission=«
"chmod +rx ${abspath}"
CDC-1.1/Foundation-1.1,OSGi/Minimum-1.2
org.osgi.framework.library.extensions= a,so,dll
org.osgi.framework.os.name The name of the operating system as used in the native code
clause. If not set, then the framework must provide a default
value. Table 4.3 defines a list of operating system names. New
operating system names are made available on the OSGi web
site, see [11] OSGi Reference Names. Names should be matched
case insensitive.
org.osgi.framework.os.version The version of the operating system as used in the native code
clause. If not set, then the framework must provide a default
value. If the operating system reported version does not fit the
standard version syntax (e.g. 2.4.32-kwt), then the launcher
should define this launching property with a valid version val-
ue.
org.osgi.framework.processor The name of the processor as used in the native code clause. If
not set, then the framework must provide a value. Table 4.2 de-
fines a list of processor names. New processors are made avail-
able on the OSGi web site, see [11] OSGi Reference Names. Names
should be matched case insensitive.
org.osgi.framework.security Specifies the type of security manager the framework must use.
If not specified then the framework will not set the VM securi-
ty manager. The following type is architected:
org.osgi.framework.security = osgi
org.osgi.framework.startlevel.« Specifies the beginning start level of the framework. See Start
Level API Specification on page 181 for more information.
beginning
org.osgi.framework.startlevel.beginning = 3
For example:
org.osgi.framework.storage.clean = onFirstInit
• osgi.ee
• osgi.native
org.osgi.framework.system.packages.extra=«
org.acme.foo; version=1.2, org.acme.foo.impl
org.osgi.framework.trust.repositories = «
/var/trust/keystore.jks:~/.cert/certs.jks
org.osgi.framework.« Provide the name of the current window system. This can be
used by the native code clause, Native Code Algorithm on page
windowsystem
80. If not set, the framework should provide a value that de-
pends on the current environment.
The properties in the following table are the fixed properties of the framework. The values of these
properties are established by the framework implementation and added to the launching properties.
If these properties are set in the configuration properties, the framework must ignore them.
All launching properties are available through the getProperty(String) method. See Environment
Properties on page 125.
• init - If the framework object is not active, then this method moves the framework object into the
STARTING state.
• start - Ensure that the framework is in the ACTIVE state. This method can be called only on the
framework because there are no bundles running yet.
• update - Stop the framework. This returns the Framework event STOPPED_UPDATE or
STOPPED_BOOTCLASSPATH_MODIFIED to the waitForStop method and then restarts the frame-
work to its previous state. The launcher should then take the appropriate action and then call
the waitForStop method again or reboot the VM. The update method can be called on the frame-
work or on the system bundle. If the framework is not active, this has no effect.
• stop - Move the framework into the RESOLVED state via the STOPPING state. This will return a
Framework STOPPED event from the waitForStop method. The Framework's Bundle Context is
no longer valid. The framework must be initialized again to get a new, valid Bundle Context. The
stop method can be called on the framework or on the system bundle.
• uninstall - Must not be called, will throw an Exception when called.
Figure 4.3 on page 109 shows how the previous methods traverse the state diagram.
newFramework
update
stop
INSTALLED
init
init STARTING
start
update init, start
stop RESOLVED start
init
stop start
update ACTIVE
stop
update stop
start update
init
STOPPING
• All resolved extension bundle activators start methods have been called
After a framework object is stopped and in the resolved state, it can be initialized and started again.
Framework implementations must ensure that holding on to a framework object does not consume
significant resources.
org.osgi.framework.uuid
The value of this property must reflect a string defined in [14] IETF RFC 1422 A Universally Unique
IDentifier (UUID) URN Namespace with the urn:uuid: prefix. For example:
f81d4fae-7dec-11d0-a765-00a0c91e6bf6
The Java UUID class is capable of generating such a UUID. However, as long as the external repre-
sentation is maintained frameworks are free to create a unique global id in another way.
Setting this property in the configuration properties has no effect, the framework must override it.
META-INF/services/org.osgi.framework.launch.FrameworkFactory
In contrast with the [13] Java Service Provider Configuration, there must only be one class name listed
in the resource. However, launchers should be aware that the class path could contain multiple re-
sources with the same name.
Java 6 has introduced the java.util.ServiceLoader class that simplifies creating objects through these
types of factories. The following code assumes there is a framework implementation JAR on the
class path:
ServiceLoader<FrameworkFactory> sl =
ServiceLoader.load(FrameworkFactory.class);
Iterator<FrameworkFactory> it = sl.iterator();
if ( it.hasNext() ) {
Framework fw = it.next().newFramework(null);
...
}
4.3 Bundles
A bundle represents a JAR file that is executed in an OSGi Framework. The class loading aspects of
this concept were specified in the Module Layer. However, the Module Layer does not define how a
bundle is installed, updated, and uninstalled. These life cycle operations are defined here.
The installation of a bundle can only be performed by another bundle or through implementation
specific means (for example as a command line parameter of the Framework implementation).
A Bundle is started through its Bundle Activator. Its Bundle Activator is identified by the Bundle-Ac-
tivator manifest header. The given class must implement the BundleActivator interface. This inter-
face has a start and stop method that is used by the bundle programmer to register itself as listener
and start any necessary threads. The stop method must clean up and stop any running threads.
Upon the activation of a bundle, it receives a Bundle Context. The Bundle Context interface's meth-
ods can roughly be divided in the following categories:
• Bundle identifier - A long that is a Framework assigned unique identifier for the full lifetime of a
bundle, even if it is updated or the Framework is restarted. Its purpose is to distinguish bundles
in a Framework. Bundle identifiers are assigned in ascending order to bundles when they are in-
stalled. The method getBundleId() returns a bundle's identifier.
• Bundle location - A name assigned by the management agent (Operator) to a bundle during the in-
stallation. This string is normally interpreted as a URL to the JAR file but this is not mandatory.
Within a particular Framework, a location must be unique. A location string uniquely identifies
a bundle and must not change when a bundle is updated. The getLocation() method retrieves
the location of a bundle.
• Bundle Symbolic Name and Bundle Version - A name and version assigned by the developer. The
combination of Bundle Version and Bundle Symbolic Name is a globally unique identifier for a
bundle. The getSymbolicName() method returns the assigned bundle name. The Bundle getVer-
sion() method returns the version. Though the pair is unique, it is possible to install the same
bundle multiple times if the org.osgi.framework.bsnversion framework launching property is
set to managed or multiple, see also Bundle Collision Hook on page 396.
• STARTING - The bundle is being started, the BundleActivator.start method will be called, and this
method has not yet returned. When the bundle has a lazy activation policy, the bundle will re-
main in the STARTING state until the bundle is activated. See Activation Policies on page 117 for
more information.
• ACTIVE - The bundle has been successfully activated and is running; its Bundle Activator start
method has been called and returned.
• STOPPING - The bundle is being stopped. The BundleActivator.stop method has been called but
the stop method has not yet returned.
• UNINSTALLED - The bundle has been uninstalled. It cannot move into another state.
install
update
UNINSTALLED uninstall INSTALLED refresh
resolve
uninstall
STARTING
update
refresh
lazy activation
start
RESOLVED ACTIVE
stop
STOPPING
When a bundle is installed, it is stored in the persistent storage of the Framework and remains there
until it is explicitly uninstalled. Whether a bundle has been started or stopped must be recorded
in the persistent storage of the Framework. A bundle that has been persistently recorded as started
must be started whenever the Framework starts until the bundle is explicitly stopped. The Start Lev-
el API influences the actual starting and stopping of bundles. See Start Level API Specification on page
181.
The Bundle interface defines a getState() method for returning a bundle's state.
If this specification uses the term active to describe a state, then this includes the STARTING and
STOPPING states.
Bundle states are expressed as a bit-mask though a bundle can only be in one state at any time. The
following code sample can be used to determine if a bundle is in the STARTING, ACTIVE, or STOP-
PING state:
• installBundle(String) - Installs a bundle from the specified location string (which should be a
URL).
• installBundle(String,InputStream) - Installs a bundle from the specified InputStream object.
A bundle must be valid before it is installed, otherwise the install must fail. The validity of a bundle
is discussed in Bundle Validity on page 83.
If the to be installed bundle has a bundle symbolic name and version pair that is already installed in
the framework then the installation is only valid when the org.osgi.framework.bsnversion frame-
work launching property is set to multiple or managed. See Bundle Collision Hook on page 396 for
more information.
Every bundle is uniquely identified by its location string. If an installed bundle is using the specified
location, the installBundle methods must return the Bundle object for that installed bundle and not
install a new bundle.
The Framework must assign a unique bundle identifier that is higher than any previous bundle
identifier.
The installation of a bundle in the Framework must be:
• Persistent - The bundle must remain installed across Framework and Java VM invocations until it
is explicitly uninstalled.
• Atomic - The install method must completely install the bundle or, if the installation fails, the OS-
Gi framework must be left in the same state as it was in before the method was called.
Once a bundle has been installed, a Bundle object is created and all remaining life cycle operations
must be performed upon this object. The returned Bundle object can be used to start, stop, update,
and uninstall the bundle.
Once a bundle is started, a bundle must be activated, see Activation on page 116, to give control
to the bundle so that it can initialize. This activation can take place immediately (eager activation),
or upon the first class load from the bundle (lazy activation). A started bundle may need to be auto-
matically started again by the framework after a restart or changes in the start level. The framework
therefore maintains a persistent autostart setting for each bundle. This autostart setting can have the
following values:
The Bundle interface defines the start(int) method for starting a bundle and controlling the au-
tostart setting. The start(int) method takes an integer option, the following values have been de-
fined for this option:
• 0 - Start the bundle with eager activation and set the autostart setting to Started with eager activa-
tion. If the bundle was already started with the lazy activation policy and is awaiting activation,
then it must be activated immediately.
• START_TRANSIENT - Identical to 0 in behavior, however, the autostart setting must not be altered.
If the bundle can not be started, for example, the bundle is not ready, then a Bundle Exception
must be thrown.
• START_ACTIVATION_POLICY - Start the bundle using the activation policy declared in the
manifest's Bundle-ActivationPolicy header and set the autostart setting to Started with declared ac-
tivation.
• START_ACTIVATION_POLICY | START_TRANSIENT - Start the bundle with the bundle's declared
activation policy but do not alter the autostart setting.
The Framework must attempt to resolve the bundle, if not already resolved, when trying to start the
bundle. If the bundle fails to resolve, the start method must throw a BundleException . In this case,
the bundle's autostart setting must still be set unless START_TRANSIENT is used.
When the start method returns without an exception, the state of the bundle will either be AC-
TIVE or STARTING, depending on the declared activation policy and whether it was used. If the
start method throws an exception, then the bundle will not be in either of these states and the stop
method will not be called for this Bundle Activator instance.
The start() method calls start(0).
The optional Start Level API influences the actual order of starting and stopping of bundles. See
Start Level API Specification on page 181' Fragment bundles can not be started and must cause a
Bundle Exception when there is an attempt to start them.
4.4.6 Activation
A bundle is activated by calling its Bundle Activator object, if one exists. The BundleActivator inter-
face defines methods that the Framework invokes when it starts and stops the bundle.
To inform the OSGi environment of the fully qualified class name serving as its Bundle Activator, a
bundle developer must declare a Bundle-Activator manifest header in the bundle's manifest file. The
Framework must instantiate a new object of this class and cast it to a BundleActivator instance. It
must then call the BundleActivator.start method to start the bundle.
The following is an example of a Bundle-Activator manifest header:
Bundle-Activator: com.acme.Activator
A class acting as a Bundle Activator must implement the BundleActivator interface, be de-
clared public, and have a public default constructor so an instance of it may be created with
Class.newInstance.
Supplying a Bundle Activator is optional. For example, a library bundle that only exports a number
of packages does not need to define a Bundle Activator. In addition, other mechanism exists to ob-
tain control and get a Bundle Context, like for example the Service Component Runtime.
The BundleActivator interface defines these methods for starting and stopping a bundle:
• start(BundleContext) - This method can allocate resources that a bundle needs, start threads, reg-
ister services, and more. If this method does not register any services, the bundle can register ser-
vices it needs later: for example, in a callback or an external event, as long as it is in the ACTIVE
state. If the start(BundleContext) method throws an exception, the Framework must mark the
bundle as stopped and send out STOPPING and STOPPED events but it must not call the Bundle
Activator stop(BundleContext) method. The start method must therefore be careful to clean up
any resources it creates in the start method when it throws an exception.
• stop(BundleContext) - This method must undo all the actions of the
BundleActivator.start(BundleContext) method. However, it is unnecessary to unregister ser-
vices or Framework listeners, because they must be cleaned up by the Framework anyway. This
method is only called when the bundle has reached the ACTIVE state. That is, when the start
method has thrown exception, the stop method is never called for the same instance.
A Bundle Activator must be created when a Bundle is started, implying the creation of a class loader.
For larger systems, this greedy strategy can significantly increase startup times and unnecessarily in-
crease the memory footprint. Mechanisms such as the Service Component Runtime and activation
policies can mitigate these problems.
Fragment bundles must not have a Bundle Activator specified.
The only policy defined is the lazy activation policy. If no Bundle-ActivationPolicy header is speci-
fied, the bundle will use eager activation.
If the activation fails because the Bundle Activator start method has thrown an exception, the bun-
dle must be stopped without calling the Bundle Activator stop method. These steps are pictured in a
flow chart in Figure 4.5. This flow chart also shows the difference in activation policy of the normal
eager activation and the lazy activation.
started?
yes
no
state=STARTING
event
STARTING
activate
the bundle
yes exception? no
state=STOPPING state=ACTIVE
event event
STOPPING STARTED
state=RESOLVED
event
STOPPED
The lazy activation policy allows a Framework implementation to defer the creation of the bundle
class loader and activation of the bundle until the bundle is first used; potentially saving resources
and initialization time during startup.
By default, any class loaded from the bundle can trigger the lazy activation, however, resource loads
must not trigger the activation. The lazy activation policy can define which classes cause the activa-
tion with the following directives:
• include - A list of package names that must trigger the activation when a class is loaded from any
of these packages. The default is all package names present in the bundle.
• exclude - A list of package names that must not trigger the activation of the bundle when a class
is loaded from any of these packages. The default is no package names.
For example:
Bundle-ActivationPolicy: lazy; «
include:="com.acme.service.base,com.acme.service.help"
When a class load triggers the lazy activation, the Framework must first define the triggering class.
This definition can trigger additional lazy activations. These activations must be deferred until all
transitive class loads and defines have finished. Thereafter, the activations must be executed in the
reverse order of detection. That is, the last detected activation must be executed first. Only after
all deferred activations are finished must the class load that triggered the activation return with
the loaded class. If an error occurs during this process, it should be reported as a Framework ERROR
event. However, the class load must succeed normally. A bundle that fails its lazy activation should
not be activated again until the framework is restarted or the bundle is explicitly started by calling
the Bundle start method.
• An ACTIVE or STARTING bundle must be started transiently after an update or refresh operation to
not change its persistent autostart state.
• If the bundle was in the STARTING state due to lazy activation, the bundle's activation policy
should be used when starting the bundle.
• 0 - If the bundle was activated, then deactivate the bundle and sets the autostart setting for this
bundle to Stopped.
• STOP_TRANSIENT - If the bundle was activated, then deactivate the bundle. Does not alter the au-
tostart setting for this bundle.
4.4.8 Deactivation
The BundleActivator interface defines a stop(BundleContext) method, which is invoked by the
Framework to stop a bundle. This method must release any resources allocated since activation.
All threads associated with the stopping bundle should be stopped immediately. The threaded code
may no longer use Framework-related objects (such as services and BundleContext objects) once the
stop method returns.
If the stopping bundle had registered any services or Framework listeners during its lifetime, then
the Framework must automatically unregister all registered services and Framework listeners when
the bundle is stopped. It is therefore unnecessary from the Framework's point of view to unregister
any services or Framework listeners in the stop method.
The Framework must guarantee that if a BundleActivator. start method has executed successfully,
that same BundleActivator object must be called with its BundleActivator.stop method when the
bundle is deactivated. After calling the stop method, that particular BundleActivator object must
never be used again.
Packages exported by a stopped bundle continue to be available to other bundles. This continued ex-
port implies that other bundles can execute code from a stopped bundle, and the designer of a bun-
dle should assure that this is not harmful. Exporting interfaces only is one way to prevent such un-
wanted execution when the bundle is not started. Generally, to ensure they cannot be executed, in-
terfaces should not contain executable code.
The update process supports migration from one revision of a bundle to a newer revision of the
same bundle. The capabilities provided by the new revision must be immediately available to the
Framework. If the old bundle revision has an isInUse() bundle wiring then all capabilities provided
by the old bundle wiring must remain available for existing bundles and future resolves until the
bundle is refreshed, see Refreshing on page 167, or the Framework is restarted. Otherwise the capa-
bilities provided by the old revision must be removed.
After the update operation is complete, the framework must attempt to move the bundle to the
same state as it was before the operation taking the activation policy into account, without chang-
ing the autostart setting. This is described in more detail in Restoring State After Refresh or Update on
page 119.
An updater of a bundle must have AdminPermission[<bundle>,LIFECYCLE] for both the installed
bundle as well as the new bundle. The parameters of AdminPermission are explained in Admin Per-
mission on page 129.
• getHeaders() - Returns a Dictionary object that contains the bundle's manifest headers and val-
ues as key/value pairs. The values returned are localized according to the default locale returned
by java.util.Locale.getDefault.
• getHeaders(String) - Returns a Dictionary object that contains the bundle's manifest headers and
values as key/value pairs. The returned values are localized using the specified locale. The locale
may take the following values:
• null - The default locale returned by java.util.Locale.getDefault is used. This makes this
method identical to the getHeaders() method.
• Empty string - The dictionary will contain the raw (unlocalized) manifest headers including
any leading '%'.
• A Specific Locale - The given locale is used to localize the manifest headers.
If the bundle is a multi-release JAR, see Multi-release JAR on page 41, then the returned manifest
header information must be the supplemented manifest information. That is, the main manifest
with the replacement values from a supplemental manifest, if any, for the current Java platform ver-
sion.
Localization is performed according to the description in Localization on page 82. If no translation is
found for a specific key, the Dictionary returned by Bundle.getHeaders will return the raw values as
specified in the manifest header values without the leading '%' character.
These methods require AdminPermission[<bundle>, METADATA ] because some of the manifest head-
er information may be sensitive, such as the packages listed in the Export-Package header. Bundles
always have permission to read their own headers.
The getHeaders methods must continue to provide the manifest header information after the bun-
dle enters the UNINSTALLED state. After the bundle has been uninstalled, this method will only re-
turn manifest headers that are raw or localized for the default locale at the time the bundle was
uninstalled.
A framework implementation must use only the raw (unlocalized) manifest headers when process-
ing manifest headers. Localizations must not influence the operations of the Framework.
For example, an application model could use this feature to load the initial class from the bundle
and start it according to the rules of the application model.
void appStart() {
Class initializer = bundle.loadClass(activator);
if ( initializer != null ) {
App app = (App) initializer.newInstance();
app.activate();
}
}
Loading a class from a bundle can cause it to be activated if the bundle uses a lazy activation policy.
ferent resource search strategy. The Bundle interface provides a number of methods that access re-
sources but use different strategies. The following search strategies are supported:
• Class Space - The getResource(String) and getResources(String) provide access to resources that
is consistent with the class space as described in Overall Search Order on page 71. Following the
search order can make certain parts of the JAR files inaccessible. These methods require that the
bundle is resolved. If the bundle is not resolved, the Framework must attempt to resolve it.
The search order can hide certain directories of the JAR file. Split packages are taken into ac-
count; therefore, resources with the same package names can come from different JARs. If the
bundle is unresolved (or cannot be resolved), the getResource and getResources methods must
only load resources from the bundle class path. This search strategy should be used by code that
wants to access its own resources. Calling either method can cause the creation of a class loader
and force the bundle to become resolved.
• JAR File - The getEntry(String) and getEntryPaths(String) methods provide access to the re-
sources in the bundle's JAR file. No searching is involved, only the raw JAR file is taken into ac-
count. The purpose of these methods is to provide low-level access without requiring that the
bundle is resolved.
• Bundle Space - The findEntries(String,String,boolean) is an intermediate form. Useful when con-
figuration or setup information is needed from another bundle. It considers Fragment bundles
but it must never create a class loader or use the bundle class path. The method provides access
to all directories in the associated JAR files.
A: Require-Bundle: D
Import-Package: q,t
Export-Package: t
B: Export-Package: q,t
C: Fragment-Host: A
D: Export-Package: s
Figure 4.6 Setup for showing the difference between getResource and getEntry
B
A q q
t t
t
p D
s
p C
r
The following table shows the effect of getting a resource from this setup when bundle A is resolved.
Table 4.5 Differences between getResource, getEntry, and findEntries for resolved bundle A
Resource getResource getEntry findEntries
q B.q null null
p A.p > C.p A.p A.p > C.p
r C.r null C.r
The following table shows the same cases as the previous table but now for an unresolved bundle A.
Table 4.6 Differences between getResource, getEntry, and findEntries for an unresolved bundle A
Resource getResource getEntry findEntries
q null null null
p A.p A.p A.p
r null null null
s null null null
t A.t A.t A.t
4.4.17 Adaptations
The adapt(Class) method allows the Bundle to be adapted to different types. The purpose of this
method is to provide more specialized access to the Bundle object, access that is not always needed
by most clients of the interface. For example, the adapt method can be used to adapt a Bundle object
to the current BundleWiring object (if resolved). The adapt method is used as follows:
BundleWiring bw = aBundle.adapt(BundleWiring.class);
The following table shows the minimum list of types that can be used in the adapt method. Howev-
er, implementations and specifications can extend this list.
Table 4.7 Minimum set of classes that can be adapted from Bundle
Class Description
AccessControlContext The Access Control Context for this bundle according to Permis-
sions of a Bundle on page 123.
BundleContext The Bundle Context for this bundle.
BundleRevision The current Bundle Revision for this bundle, see Bundle Wiring
API Specification on page 157.
Class Description
BundleRevisions All existing Bundle Revision objects for this bundle, see Bundle
Wiring API Specification on page 157.
BundleStartLevel The Bundle Start Level for this bundle, see Start Level API Specifi-
cation on page 181.
BundleWiring The Bundle Wiring for the current Bundle Revision, see Bundle
Wiring API Specification on page 157.
Framework The Framework object from the launching API if this bundle is
the System Bundle, see Frameworks on page 100.
FrameworkStartLevel The Framework Start Level if this is the System Bundle, see Start
Level API Specification on page 181.
FrameworkWiring The Framework Wiring if this bundle is the System Bundle. See
Bundle Wiring API Specification on page 157.
• Installing new bundles into the OSGi environment. See Installing Bundles on page 114.
• Interrogating other bundles installed in the OSGi environment. See Getting Bundle Information on
page 124.
• Obtaining a persistent storage area. See Persistent Storage on page 125.
• Retrieving service objects of registered services. See Service References on page 135.
• Registering services in the Framework service. See Registering Services on page 135.
• Subscribing or unsubscribing to events broadcast by the Framework. See Listeners on page 127.
When a bundle is started, the Framework creates a BundleContext object and provides this object as
an argument to the start(BundleContext) method of the bundle's Bundle Activator. Each bundle is
provided with its own BundleContext object; these objects should not be passed between bundles,
since the BundleContext object is related to the security and resource allocation aspects of a bundle.
After the stop(BundleContext) method has returned, the BundleContext object must no longer be
used. Framework implementations must throw an exception if the BundleContext object is used af-
ter a bundle is stopped.
The BundleContext object is only valid during the { STARTING, ACTIVE, STOPPING } states of a bun-
dle. However, the BundleContext object becomes invalid after stop(BundleContext) returns (if the
bundle has a Bundle Activator). The BundleContext object becomes invalid before disposing of any
remaining registered services and releasing any remaining services in use. Since those activities can
result in other bundles being called (for example, Service Listeners for UNREGISTERING events and
Service Factories for unget operations), those other bundles can observe the stopping bundle in the
STOPPING state but with an invalid BundleContext object.
• getBundle() - Returns the single Bundle object associated with the BundleContext object.
Bundle access is not restricted; any bundle can enumerate the set of installed bundles. Information
that can identify a bundle, however (such as its location, or its header information), is only provided
to callers that have AdminPermission[<bundle>,METADATA].
• The system bundle has a bundle symbolic name that is unique for a specific version. However,
the name system.bundle must be recognized as an alias to this implementation-defined name.
• The system bundle's life cycle cannot be managed like normal bundles. Its life cycle methods
must behave as follows:
• start - Does nothing because the system bundle is already started.
• stop - Returns immediately and shuts down the Framework on another thread.
• update - Returns immediately, then stops and restarts the Framework on another thread.
• uninstall - The Framework must throw a BundleException indicating that the system bundle
cannot be uninstalled.
See Frameworks on page 100 for more information about the starting and stopping of the
Framework.
4.7 Events
The OSGi Framework Life Cycle layer supports the following types of events:
The actual event that is reported is available with the getType method. The integer that is returned
from this method can be one of the constant names that are described in the class. However, events
can, and will be, extended in the future. Unrecognized event types should be ignored.
4.7.1 Listeners
A listener interface is associated with each type of event. The following list describes these listeners.
• STARTLEVEL_CHANGED - Is sent by the Framework after a new start level has been set and
processed.
• STOPPED - Sent by the Framework because of a stop operation on the system bundle.
• STOPPED_BOOTCLASSPATH_MODIFIED - Sent by the Framework because of a stop operation
on the system bundle and a boot class path extension bundle has been installed or updated.
• STOPPED_UPDATE - Sent by the Framework because of an update operation on the system
bundle. The Framework will be restarted after this event is fired.
• WARNING - A warning to the operator that is not crucial but may indicate a potential error sit-
uation.
• WAIT_TIMEDOUT - Returned from the waitForStop method when the Framework did not stop
before the given wait time-out expired.
BundleContext interface methods are defined which can be used to add and remove each type of lis-
tener.
Events can be asynchronously delivered, unless otherwise stated, meaning that they are not neces-
sarily delivered by the same thread that generated the event. The thread used to call an event listen-
er is not defined.
The Framework must publish a FrameworkEvent.ERROR if a callback to an event listener
generates an unchecked exception - except when the callback happens while delivering a
FrameworkEvent.ERROR (to prevent an infinite loop).
Synchronous events have the unfortunate effect that, in rare cases, events can be delivered out of
order to a listener. For example, a Service Event UNREGISTERING can be delivered before its corre-
sponding Service Event REGISTERED. One pathological case is when a service listener (for example a
Service Tracker) unregisters a service that it receives in the REGISTERED event for. If there are listen-
ers queued behind the pathological listener then they see the unregistering before they see the regis-
tration.
• Collect a snapshot of the listener list at the time the event is published (rather than doing so in
the future just prior to event delivery), but before the event is delivered, so that listeners do not
enter the list after the event happened.
• Ensure, at the time the snapshot is taken, that listeners on the list still belong to active bundles at
the time the event is delivered.
• It is possible to use more than one thread to deliver events. If this is the case then each handler
must receive the events in the same order as the events were posted. This ensures that handlers
see events in the expected order.
If the Framework did not capture the current listener list when the event was published, but instead
waited until just prior to event delivery, then the following error could occur: a bundle could have
started and registered a listener, and then the bundle could see its own BundleEvent.INSTALLED
event.
The following three scenarios illustrate this concept.
4.8 Security
4.8.1 Admin Permission
The Admin Permission is a permission used to grant the right to manage the Framework with the
option to restrict this right to a subset of bundles, called targets. For example, an Operator can give a
bundle the right to only manage bundles of a signer that has a subject name of ACME:
org.osgi.framework.AdminPermission(
"(signer=\*, o=ACME, c=us)", ... )
The actions of the Admin Permission are fine-grained. They allow the deployer to assign only the
permissions that are necessary for a bundle. For example, an HTTP implementation could be grant-
ed access to all resources of all bundles.
org.osgi.framework.AdminPermission("*",
"resource" )
Code that needs to check Admin Permission must always use the constructor that takes a bundle as
parameter: AdminPermission(Bundle,String) with a single action.
For example, the implementation of the loadClass method must check that the caller has access to
the class space:
The Admin Permission takes a filter as its name. Filter based permissions are described in Filter Based
Permissions on page 29.
4.8.1.1 Actions
The action parameter of Admin Permission will specify the subset of privileged administrative op-
erations that are allowed by the Framework. The actions that are architected are listed in the follow-
ing table. Future versions of the specification, as well as additional system services, can add addi-
tional actions. The given set should therefore not be assumed to be a closed set.
Table 4.9 Admin Permission actions
Action Used in
METADATA Bundle.getHeaders
Bundle.getLocation
RESOURCE Bundle.getResource
Bundle.getResources
Bundle.getEntry
Bundle.getEntryPaths
Bundle.findEntries
Bundle resource/entry URL creation
CLASS Bundle.loadClass
LIFECYCLE BundleContext.installBundle
Bundle.update
Bundle.uninstall
EXECUTE Bundle.start
Bundle.stop
BundleStartLevel.setBundleStartLevel
LISTENER BundleContext.addBundleListener for SynchronousBundleListener
BundleContext.removeBundleListener for SynchronousBundleListener
EXTENSIONLIFECYLE BundleContext.installBundle for extension bundles
Bundle.update for extension bundles
Bundle.uninstall for extension bundles
RESOLVE FrameworkWiring.refreshBundles
FrameworkWiring.resolveBundles
STARTLEVEL FrameworkStartLevel.setStartLevel
FrameworkStartLevel.setInitialBundleStartLevel
Action Used in
CONTEXT Bundle.getBundleContext
WEAVE WovenClass.setBytes
WovenClass.getDynamicImports
• BundleActivator
• ServiceFactory
• BundleListener, ServiceListener, and FrameworkListener
• Framework hook services
When any of these callbacks are invoked by the Framework, the bundle that caused the callback
may still be on the stack. For example, when one bundle installs and then starts another bundle, the
installer bundle may be on the stack when the BundleActivator.start method of the installed bundle
is called. Likewise, when a bundle registers a service object, it may be on the stack when the Frame-
work calls back the serviceChanged method of all qualifying ServiceListener objects.
Whenever any of these bundle callbacks try to access a protected resource or operation, the access
control mechanism should consider not only the permissions of the bundle receiving the callback,
but also those of the Framework and any other bundles on the stack. This means that in these call-
backs, bundle programmers normally would use doPrivileged calls around any methods protected
by a permission check (such as getting or registering service objects).
In order to reduce the number of doPrivileged calls by bundle programmers, the Framework
must perform a doPrivileged call around any bundle callbacks. The Framework should have
java.security.AllPermission. Therefore, a bundle programmer can assume that the bundle is not fur-
ther restricted except for its own permissions.
Bundle programmers do not need to use doPrivileged calls in their implementations of any call-
backs registered with and invoked by the Framework.
For any other callbacks that are registered with a service object and therefore get invoked by the ser-
vice-providing bundle directly, doPrivileged calls must be used in the callback implementation if
the bundle's own privileges are to be exercised. Otherwise, the callback must fail if the bundle that
initiated the callback lacks the required permissions.
A framework must never load classes in a doPrivileged region, but must instead use the current
stack. This means that static initializers and constructors must not assume that they are privileged.
Any privileged code in a static initializer must be guarded with a doPrivileged region in the static
initializer. Likewise, a framework must not instantiate a BundleActivator object in a doPrivileged re-
gion, but must instead use the current stack. This means that the BundleActivator constructor must
not assume that it is privileged.
Normal class loading caused by executing Java class code must not require
AdminPermission[*,EXECUTE ].
4.9 References
[1] The Standard for the Format of ARPA Internet Text Messages
STD 11, RFC 822, UDEL, August 1982
http://www.ietf.org/rfc/rfc822.txt
[2] The Hypertext Transfer Protocol - HTTP/1.1
RFC 2068 DEC, MIT/LCS, UC Irvine, January 1997
http://www.ietf.org/rfc/rfc2068.txt
[3] Java Language Specification
https://docs.oracle.com/javase/specs/
[4] A String Representation of LDAP Search Filters
RFC 1960, UMich, 1996
http://www.ietf.org/rfc/rfc1960.txt
[5] Java Security Architecture
https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc.html
[6] Java Package Versioning Specification
https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/index.html
[7] Codes for the Representation of Names of Languages
ISO 639, International Standards Organization
http://lcweb.loc.gov/standards/iso639-2/langhome.html
[8] Manifest Format
https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#JAR_Manifest
[9] W3C EBNF
http://www.w3c.org/TR/REC-xml#sec-notation
[10] Interval Notation
http://www.math.ohio-state.edu/courses/math104/interval.pdf
[11] OSGi Reference Names
https://www.osgi.org/developer/specifications/reference/
[12] JKS Keystore Format (reverse engineered)
http://metastatic.org/source/JKS.html
[13] Java Service Provider Configuration
https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Service_Provider
[14] IETF RFC 1422 A Universally Unique IDentifier (UUID) URN Namespace
http://www.ietf.org/rfc/rfc4122.txt
4.10 Changes
• Launching property org.osgi.framework.storage must be set when default value used.
• Added support for multi-release JARs. See Detecting Bundle Modifications on page 120 and Re-
trieving Manifest Headers on page 120.
5 Service Layer
Version 1.9
5.1 Introduction
The OSGi Service Layer defines a dynamic collaborative model that is highly integrated with the
Life Cycle Layer. The service model is a publish, find and bind model. A service is a normal Java ob-
ject that is registered under one or more Java interfaces with the service registry. Bundles can regis-
ter services, search for them, or receive notifications when their registration state changes.
5.1.1 Essentials
• Collaborative - The service layer must provide a mechanism for bundles to publish, find, and bind
to each other's services without having a priori knowledge of those bundles.
• Dynamic - The service mechanism must be able to handle changes in the outside world and un-
derlying structures directly.
• Secure - It must be possible to restrict access to services.
• Reflective - Provide full access to the Service Layer's internal state.
• Versioning - Provide mechanisms that make it possible to handle the fact that bundles and their
services evolve over time.
• Persistent Identifier - Provide a means for bundles to track services across Framework restarts.
5.1.2 Entities
• Service - An object registered with the service registry under one or more interfaces together with
properties. The service can be discovered and used by bundles.
• Service Registry - Holds the service registrations.
• Service Reference - A reference to a service. Provides access to the service's properties but not the
actual service object. The service object must be acquired through a bundle's Bundle Context.
• Service Registration - The receipt provided when a service is registered. The service registration al-
lows the update of the service properties and the unregistration of the service.
• Service Permission - The permission to use an interface name when registering or using a service.
• Service Scope - Indicates how service objects are obtained when requesting a service object. The
following service scopes are defined: singleton, bundle, and prototype. The default service scope is
singleton.
• Service Factory - A facility to let the registering bundle customize the service object for each using
bundle. When using a Service Factory, the service scope of the service is bundle.
• Prototype Service Factory - A facility to let the registering bundle customize the service object for
each caller. When using a Prototype Service Factory, the service scope of the service is prototype.
• Service Objects - A facility to let the using bundle obtain multiple service objects for a service with
prototype service scope.
• Service Listener - A listener to Service Events.
• Service Event - An event holding information about the registration, modification, or unregistra-
tion of a service object.
• Filter - An object that implements a simple but powerful filter language. It can select on proper-
ties.
• Invalid Syntax Exception - The exception thrown when a filter expression contains an error.
registers
service
0,1 1 0,1
1 0..n 1
<<interface>> Service Registry <<interface>>
0..n 0..n Service Listener
Prototype Impl
Service Factory
1
1
<<interface>> 1 1 <<interface>> <<interface>>
Service Service All Service
Reference Registration Listener
5.2 Services
In the OSGi framework, bundles are built around a set of cooperating services available from a
shared service registry. Such an OSGi service is defined semantically by its service interface and imple-
mented as a service object.
The service interface should be specified with as few implementation details as possible. OSGi has
specified many service interfaces for common needs and will specify more in the future.
The service object is owned by, and runs within, a bundle. This bundle must register the service ob-
ject with the Framework service registry so that the service's functionality is available to other bun-
dles under control of the Framework.
Dependencies between the bundle owning the service and the bundles using it are managed by the
Framework. For example, when a bundle is stopped, all the services registered with the Framework
by that bundle must be automatically unregistered.
The Framework maps services to their underlying service objects, and provides a simple but power-
ful query mechanism that enables a bundle to request the services it needs. The Framework also pro-
vides an event mechanism so that bundles can receive events of services that are registered, modi-
fied, or unregistered.
The names of the service interfaces under which a bundle wants to register its service are provided
as arguments to the registerService methods. The Framework must ensure that the service object
actually is an instance of each specified service interfaces, unless the object is a Service Factory. See
Service Factory on page 146 and Prototype Service Factory on page 146.
To perform this check, the Framework must load the Class object for each specified service interface
from either the bundle or a shared package. For each Class object, Class.isInstance must be called
and return true on the Class object with the service object as the argument.
The service object being registered may be further described by a Dictionary object, which contains
the properties of the service as a collection of key/value pairs.
The service interface names under which a service object has been successfully registered are auto-
matically added to the service's properties under the key objectClass. This value must be set auto-
matically by the Framework and any value provided by the bundle must be overridden.
If the service object is successfully registered, the Framework must return a ServiceRegistration ob-
ject to the caller. A service object can be unregistered only by the holder of its ServiceRegistration
object (see the unregister() method). Every successful service object registration must yield a unique
ServiceRegistration object even if the same service object is registered multiple times.
Using the ServiceRegistration object is the only way to reliably change the service's properties after
it has been registered (see the setProperties(Dictionary) method). Modifying a service's Dictionary
object after the service object is registered may not have any effect on the service's properties.
The process of registering a service object is subject to a permission check. The registering bundle
must have ServicePermission[<name>,REGISTER] to register the service object under all the service
interfaces specified. Otherwise, the service object must not be registered, and a SecurityException
must be thrown.
registerService
deliver event
The registerService
method has not get service
returned yet, so there
callback
is no ServiceRegistration
object
return
return
In a case as described previously, access to the registration object can be obtained via a ServiceFac-
tory object or PrototypeServiceFactory object. If a ServiceFactory object or PrototypeServiceFac-
tory object is registered, the Framework must call-back the registering bundle with the Service-
Factory method getService(Bundle,ServiceRegistration) or the PrototypeServiceFactory method
getService(Bundle,ServiceRegistration). The required ServiceRegistration object is passed as a pa-
rameter to these methods.
Table 5.1 Standard Service Properties (+ indicates scalar, array of, or collection of)
†
The values for these service properties must be set by the Framework. Any values specified for
these service properties during service registration or service properties update must be ignored.
This ordering is complete because service ids are never reused and handed out in order of their reg-
istration time. That is, a service that is registered later will have a higher service id. Therefore, the
ranking order is in descending service.ranking numeric order where ties give a preference to the ear-
lier registrant.
The ranking order is the reverse of the natural ordering of a ServiceReference object.
The purpose of the ranking order is to allow:
• Selection - When a single service must be chosen but multiple services qualify then the service
with the highest ranking must be selected.
• Ordering - When multiple services must be used in a specified order.
If no matching service objects are registered then null must be returned by the
getServiceReferences(String,String) method and an empty collection must be returned by the
getServiceReferences(Class,String) method.
The caller receives zero or more ServiceReference objects. These objects can be used to retrieve
properties of the underlying service, or they can be used to obtain the actual service object. See Get-
ting Service Objects on page 141.
The above methods require that the caller has the necessary ServicePermission[ServiceReference,
GET] to get the service object for the returned Service Reference. If the caller lacks the required per-
mission, these methods must not include that Service Reference in the result.
Both of these methods must continue to provide information about the referenced service object,
even after it has been unregistered from the Framework. This requirement can be useful when a
ServiceReference object is stored with the Log Service.
• getRegisteredServices() - Returns the ServiceReference objects for the service objects that the
bundle has registered with the Framework.
• getServicesInUse() - Returns the ServiceReference objects for the service objects that the bundle
is currently using.
• SCOPE_SINGLETON - Identifies the registered service object as a single service object which will
be used by all bundles requesting the service object.
• SCOPE_BUNDLE - Identifies the registered service object as a Service Factory. A Service Factory
allows the registering bundle to customize the service object for each bundle requesting the ser-
vice object. See Service Factory on page 146
• SCOPE_PROTOTYPE - Identifies the registered service object as a Prototype Service Factory. A Pro-
totype Service Factory allows the registering bundle to customize the service object for each re-
quest for the service object. See Prototype Service Factory on page 146.
The Framework must set the SERVICE_SCOPE service property automatically depending on the
type of registered service object. If the registered service object implements PrototypeServiceFac-
tory, then the value must be SCOPE_PROTOTYPE. Otherwise, if the registered service object im-
plements ServiceFactory, then the value must be SCOPE_BUNDLE. Otherwise, the value must be
SCOPE_SINGLETON. The SERVICE_SCOPE service property allows bundles to determine whether
multiple service objects can be obtained for the service. Component models like Declarative Ser-
vices and Blueprint need to know if they can properly obtain multiple service objects for referenced
services.
These methods are used to obtain an actual service object so that the Framework can manage depen-
dencies. If a bundle retrieves a service object, that bundle becomes dependent upon the life cycle of
the registered service object. This dependency is tracked by the BundleContext object used to obtain
the service object, directly or indirectly by a ServiceObjects object, and is one reason that it is im-
portant to be careful when sharing BundleContext and ServiceObjects objects with other bundles.
The ServiceObjects.getService() method will only return a single service object for the bundle
if the service has SCOPE_SINGLETON or SCOPE_BUNDLE scope. That is, the method behaves the
same as the BundleContext.getService(ServiceReference) method and only a single service object is
available. See Getting a Single Service Object on page 141.
• If the usage count of the service for this BundleContext object is zero or the service has been un-
registered, false is returned.
• The usage count of the service for this BundleContext object is decremented by one.
• If the usage count of the service for this BundleContext object is now zero and the service has
SCOPE_BUNDLE or SCOPE_PROTOTYPE scope, the registered service object is cast to a Service-
• If the associated service has been unregistered, this method returns without doing anything.
• If the specified service object is null or was not provided by a ServiceObjects for the associated
service, then an IllegalArgumentException is thrown.
• The usage count for the specified service object is decremented.
• If the usage count for the specified service object is now zero, the registered service object is
cast to a PrototypeServiceFactory object and the ungetService(Bundle,ServiceRegistration,S)
method is called to release the specified service object . The specified service object must be un-
referenced by the Framework so it may be garbage collected. See Prototype Service Factory on page
146 for more information about PrototypeServiceFactory objects.
A bundle that uses a service object should register a ServiceListener object to track the availability
of the service object, and take appropriate action when the service object is unregistering.
• REGISTERED - A service object has been registered. This event is synchronously delivered after
the service object has been registered with the Framework.
• MODIFIED - The properties of a service have been modified. This event is synchronously deliv-
ered after the service properties have been modified.
• MODIFIED_ENDMATCH - Listeners registered with a filter can not see the MODIFIED event when
a modification makes the filter no longer match. The lack of this notification complicates track-
ing a service with a filter. The MODIFIED_ENDMATCH event is therefore delivered if the old ser-
vice properties matched the given filter but the modified properties do not. This event is syn-
chronously delivered after the service properties have been modified.
• UNREGISTERING - A service object is in the process of being unregistered. This event is synchro-
nously delivered before the service object has completed unregistering. That is, during the deliv-
ery of this event, the service object is still valid. The bundle receiving this event must release all
references to this service before this method returns.
The behavior of a service object that becomes unregistered is undefined. Such service objects may
continue to work properly or throw an exception at their discretion. This type of error should be
logged.
5.8 Filters
The Framework provides a Filter interface, and uses a filter syntax in the getServiceRefer-
ences methods that is defined in Filter Syntax on page 39. Filter objects can be created by calling
BundleContext.createFilter(String) or FrameworkUtil.createFilter(String) with the chosen filter
string. The filter supports the following match methods:
• match(ServiceReference) - Match the properties of the Service Reference performing key lookup
in a case insensitive way.
• match(Dictionary) - Match the entries in the given Dictionary object performing key lookup in a
case insensitive way.
• matchCase(Dictionary) - Match the entries in the given Dictionary object performing key lookup
in a case sensitive way.
• matches(Map) - Match the entries in the given Map object. The map defines the
case sensitivity of the match, standard maps are case sensitive but for example a
TreeMap(String.CASE_INSENSITIVE_ORDER) provides a case insensitive map.
A Filter object can be used numerous times to determine if the match argument, a ServiceReference
object, a Map object, or a Dictionary object, matches the filter string that was used to create the Filter
object.
This matching requires comparing the value string in the filter to a target object from the service
properties or dictionary. This comparison can be executed with the Comparable interface if the tar-
get object's class implements the Comparable interface. If the target object's class does not imple-
ment Comparable, the =, ~=, <= >= operators must return only true when the objects are equal (using
the equals(Object) method).
The value string in the filter can be converted into an object suitable for comparison with the tar-
get object if the target object's class implements either a static valueOf method taking a single String
object or a constructor taking a single String object. That is, if the target object is of class Target, the
class Target must implement one of the following methods:
public B(String s) {
for ( index=0; index<keys.length; index++ )
if ( keys[index].equals(s) )
return;
}
The Filter.toString method must always return the filter string with unnecessary white space re-
moved.
objects that maintain state for the duration of usage and the using bundles require multiple service
objects at the same time.
When the customized service objects are no longer used by a bundle - for example, when that bun-
dle is stopped - then the Framework must notify the PrototypeServiceFactory object to release all
the customized service objects.
PrototypeServiceFactory objects help manage bundle dependencies that are not explicitly man-
aged by the Framework. By binding a returned service object to the requesting bundle and optional-
ly some other stateful information, the Prototype Service Factory can be notified when that bundle
ceases to use a customized service object, such as when it is stopped, and release resources associat-
ed with providing a customized service object to that bundle.
The PrototypeServiceFactory interface defines the following methods:
• Completely removed from the Framework service registry. Therefore, ServiceReference objects
obtained for that service object can no longer be used to access a service object. Attempts to get a
service object must return null.
• Unregistered, even if other bundles had dependencies upon it. Bundles must be notified of the
unregistration through the publishing of a ServiceEvent of type UNREGISTERING. This event is
sent synchronously in order to give bundles the opportunity to release service objects.
After receiving an event of type UNREGISTERING, a bundle should release the service objects and
release any references it has to the service objects, so that the service objects can be garbage col-
lected by the Java VM.
• Released by all using bundles. For each bundle with unreleased service objects after all invoked
ServiceListener objects have returned, the Framework must release all the service objects.
• getServiceReference(String)
• getServiceReference(Class)
• getServiceReferences(String,String)
• getServiceReferences(Class,String)
5.13 Security
5.13.1 Service Permission
A ServicePermission has the following parameters.
• target - Either the interface name or a filter expression for the GET action. The interface name
may end with a wildcard to match multiple interface names. See java.security.BasicPermission
for a discussion of wildcards. Filters are explained in Filter Based Permissions on page 29. The fil-
ter expression can additionally test for the service interface name with the objectClass key. Ad-
ditionally, a service permission can also test for service properties that are part of the service reg-
istration. In general, all the service properties are usable in the filter expression. However, when
there is a name conflict with the bundle identification properties, then the key can be prefixed
with the commercial at sign ('@' \u0040). For example, @id will refer to a service property with
the name id.
• action - Supported actions are:
• REGISTER - Indicates that the permission holder may register the service object
• GET - Indicates that the holder may get the service.
When an object is being registered as a service object using BundleContext.registerService, the reg-
istering bundle must have the ServicePermission to register all the named classes. See Registering
Services on page 135.
When a ServiceReference object is obtained from the service registry, see Locating Services on page
139, the calling bundle must have the required ServicePermission[ServiceReference, GET] to get
the service object for each returned Service Reference.
When a service object is obtained using a ServiceReference object, see Getting Service Objects on page
141, the calling code must have the required ServicePermission[ServiceReference, GET] to get
the service object associated with the Service Reference.
ServicePermission must be used as a filter for the service events received by the Service Listener,
as well as for the methods to enumerate services, including Bundle.getRegisteredServices and
Bundle.getServicesInUse. The Framework must assure that a bundle must not be able to detect the
presence of a service that it does not have permission to access.
5.14 Changes
• Updated Prototype Service Factory on page 146 to specify that customized service objects must
be use counted.
6.1 Introduction
This section describes the API for the generic Requirement-Capability model as introduced in the
Dependencies on page 42. This API is not used directly by the Framework, the purpose of specifying
this base API is to allow it to be used as building block for other specifications.
6.1.1 Entities
• Resource - An entity that can be installed in an Environment where it will provide its Capabilities
when all its Requirements are satisfied.
• Environment - A framework or container that contains one or more Resources.
• Namespace - Defines the semantics of the Requirements and Capabilities; a Requirement can only
match a Capability when they are in the same Namespace. A Namespace is similar to a type in an
object oriented language.
• Requirement - An assertion on a Capability in a Namespace. The assertion uses the OSGi filter lan-
guage to match the attributes of a Capability. The filter is specified as a directive; a Requirement
can also have other directives and attributes.
• Capability - An attribute based description of a quality of a Resource when installed in an Envi-
ronment.
• Wiring - The wired state of a Resource.
• Wire - Connects a Requirement to a matching Capability.
0..n
1 1
Namespace <<interface>> provided 0..n <<interface>>
has 0..1 <<interface>>
Resource Wiring 0..n Wire
required
1 1
0..n
<<interface>>
Capability 1 provider for
declares 0..n
provider for
6.2 Resources
The OSGi dependency model is introduced in Dependencies on page 42 ; it is based on a generic Re-
quirements/Capability model. In this model a Resource models something that can be installed in an
Environment but has Requirements that must be satisfied by Capabilities available in that the Envi-
ronment. However, once it is installed and resolved into the Environment it provides its declared
Capabilities to that Environment. Bundles are Resources, an example of a Requirement is an Im-
port-Package clause, and an example of a Capability is an Export-Package clause.
The org.osgi.resource package contains a base API that defines a number of interfaces that model
this generic model.
The org.osgi.framework.wiring package provides an API for reflecting the wiring of an OSGi Frame-
work. The purpose of the separation is to allow the management agents to treat the system in a uni-
form way. That is, it allows a wide array of resources and environments to be modeled, and thus
managed, in a uniform way. The Resource API is therefore primarily a building block for other speci-
fications.
The Capability and Requirement class are almost identical in their signature. They both provide the
following methods:
The key difference between a Requirement and a Capability is that a Capability provides attributes
that are matched by an OSGi filter specified in a Requirement's filter directive.
6.3 Namespaces
The Namespace acts as the type of a Capability and Requirement. A Capability and a Requirement
can only match when they are in the same Namespace. The Namespaces in use by the OSGi Core
specification are defined in Framework Namespaces Specification on page 171. Other specifications
can, however, define their own Namespaces.
A Namespace defines:
• Requirement Attributes - Any attributes that are allowed to be used on a Requirement declaration.
• Requirement Directives - Any directives that are allowed to be used on a Requirement declaration.
• Capability Attributes - Any attributes that are allowed to be used on a Capability, these attributes
are available for matching.
• Capability Directives - Any defined directives that are allowed to be used on the Capability
• Semantics - The Namespace definition defines what the meaning is of a Capability. This can in-
clude actions in the Environment like for example being wired with certain rules.
6.3.1 Matching
A Requirement matches a Capability when:
6.4 Resolution
Before a Resource can provide its functionality it must be resolved against the Environment. The
Environment can provide a number of Capabilities of its own but in general the Capabilities come
from the of the installed Resources. The resolver must find a set of Wires between Requirements and
Capabilities in an Environment such that each mandatory Requirement is satisfied with at least one
Capability, and the constraints of the involved Namespaces are all met.
Resolving is an NP-complete problem since there are many solutions, it is easy to test if a solution is
right, but there is no algorithm to calculate a solution. In practice, for the OSGi resolvers it is possi-
ble to find solutions in a reasonable amount of time. However, the nature of NP-complete problems
makes it difficult to set exact rules: many solutions are correct. Constraining the resolvers too much
would stifle innovation and likely cause performance problems.
In general the Environment has an existing Wiring state for already installed Resources. The re-
solver then calculates a resolution, which is a set of Wires that should be added to the existing
Wiring state by installing the Resources. A Wire is a connection from a Requirement to a Capability.
A Requirement or Capability is declared in a Resource. This is depicted in Figure 6.2.
wire Requirement
declared Capability
Resource
For this reason, the Wire class provides the following methods:
6.4.2 Resolution
Requirements can be optional or mandatory, as specified in the resolution directive, which is only
available on the Requirement. Optional Requirements do not have to be satisfied by the Resolver.
Environments can be eager or relaxed in finding Resources to resolve optional Requirements. All
mandatory Requirements of a Resource must be satisfied before that Resource's Capabilities can be
provided to the Environment.
The syntax of the resolution directive is therefore:
6.4.3 Effectiveness
Both Requirements and Capabilities support the effective directive. This directive provides a name
that can be used by the Environment to control the resolving process. During a resolve process, the
Environment can then decide one or more names that must match the effective directive.
For the OSGi Framework, the name resolve is reserved, this is also the default. The syntax is there-
fore:
6.4.5 Cardinality
The cardinality directive defines if a Requirement can be wired to multiple Capabilities or must be
wired to at most one. The syntax for the directive is:
6.5 Wiring
A resolver calculates a set of Wires between Requirements and Capabilities based on an existing, po-
tentially empty, state. The existing state in the Environment is represented in a set of Wiring objects.
Such an object represents the Wiring state of a Resource in an Environment. It provides access to all
hosted Requirements and Capabilities as well as existing Wires. It has the following methods to con-
veniently provide access to the state:
7.1 Introduction
A key aspect of the OSGi framework is managing the dependencies between the bundles. These de-
pendencies are expressed as manifest headers that can be grouped into requirements and capabilities
as defined in Resource API Specification on page 151. For example, an Export-Package clause is a capa-
bility and an Import-Package clause is a requirement. During the resolving phase the requirements
are resolved to matching capabilities by creating a Bundle Wire. Some of the wires can influence how
the classes are loaded from bundles during runtime.
This section outlines the API to introspect the wiring between the requirements and capabilities of
resolved bundles.
7.1.1 Entities
• Bundle Revision - Represents the class/resource container of an install or update (that is, the JAR,
directory, or other form of archive). Each update creates a new Bundle Revision and an uninstall
removes the Bundle Revisions. A Bundle Revision is modeled after a Resource.
• Namespace - Bundle Requirements and Bundle Capabilities are defined in a namespace, name-
spaces define the semantics of the requirements and capabilities. The osgi.wiring.bundle,
osgi.wiring.host and osgi.wiring.package from the Framework Namespaces are defined in Frame-
work Namespaces Specification on page 171.
• Bundle Requirement - Represents a requirement header, either the Require-Capability header or
any of the manifest headers referred to in the Framework Namespaces Specification on page 171
that map to a requirement.
• Bundle Capability - A quality of a Bundle Revision that is provided when the revision is installed.
Implemented as a set of attributes that are part of a namespace. A Bundle Capability represents
either the Provide-Capability manifest header clauses, or any headers defined in the OSGi name-
spaces that map to a capability.
• Bundle Wiring - Created each time when a Bundle Revision is resolved for holding the wires to
other Bundle Wirings as well as maintaining the run time state. Used by the framework to con-
trol class loading depending on the semantics of the OSGi namespaces.
• Bundle Wire - Connects a Bundle Requirement to a Bundle Capability as well as the requirer Bun-
dle Wiring and provider Bundle Wiring.
• Framework Wiring - Provides access to manage and initiate refresh and resolving.
<<interface>>
Wire
7.2.1 Synopsis
The Bundle Context installBundle method installs a bundle and returns a Bundle object. This install
provides the classes and resources in a JAR, directory or some other form, as an environment. This re-
source is represented as a Bundle Revision.
A Bundle Revision declares a number of Bundle Capabilities as well as a number of Bundle Require-
ments. A capability represents a set of attributes and a requirement is a filter on those attributes. For
a requirement to be applicable to a capability, they must reside in the same namespace. The name-
space groups requirements and capabilities and defines the semantics for a resolved requirement/ca-
pability pair. This pair is represented as a Bundle Wire.
Capabilities can be anything: certificates, screen size, the packages, the bundle itself or the capabili-
ty to act as host for a fragment. Some capabilities and requirements are from the Provide-Capability
and Require-Capability headers, others are defined by the OSGi headers defined in Module Layer on
page 33, the namespaces for these OSGi specific headers are defined in Framework Namespaces Speci-
fication on page 171.
The framework wires the Bundle Requirements to Bundle Capabilities during the resolving opera-
tion. The framework must resolve all the requirements to matching capabilities according to the se-
mantics of their namespaces before it can declare a bundle to be resolved. For generic namespaces
it is sufficient to find a matching capability for each requirement. However, for the OSGi name-
spaces additional rules are implied. For example, the osgi.wiring.host namespace implies all the
rules around OSGi fragment bundles.
Once a bundle is in the RESOLVED state it gets a Bundle Wiring, the Bundle Wiring represents the
run time state of the Bundle Revision. The Bundle Wiring holds the Bundle Wires. A Bundle Wire ties
a single Bundle Requirement to a single Bundle Capability as well as tying the Bundle Wiring that
holds the requirement to the Bundle Wiring that holds the capability. The Bundle Wires that flow
from a Bundle Wiring's Requirement to a capability are the required wires, they can be obtained with
getRequiredWires(String). Bundle Wires that come from a Bundle Wiring's Capability to a require-
ment are the provided wires, they can be obtained with getProvidedWires(String). The same require-
ments and capabilities can be used in different wires.
Namespace rules can be complex. For example, in the case of fragments they imply that any ca-
pabilities from the fragment are actually available from its hosts. In the case of exported pack-
ages that are also imported the resolver can choose to pick either. These examples demonstrate
that the resolver must be able to differentiate between the Bundle Revision's declared require-
ments and capabilities and the run time state, the Bundle Wiring, of the corresponding Bundle Re-
vision. A Bundle Revision's Bundle Wiring therefore provides the actual run time requirements
and capabilities as chosen by the resolver with the Bundle Wiring's getRequirements(String) and
getCapabilities(String) methods. Any optional declared requirements that were not satisfied are
not in the list of requirements. All dynamic requirements that can potentially be satisfied at run
time are in this requirements list.
The BundleWiring objects are therefore not necessarily associated with the same Bundle Revisions
that originate the declared Bundle Requirement and the declared Bundle Capability. It is therefore
that the diagramming technique used in Figure 7.2 uses dotted lines for the Bundle Wiring connec-
tion. That is, the connections from the Bundle Wire to the requirer BundleWiring object and to the
provider BundleWiring object. It then uses solid lines for the connection to the declared require-
ment and capability in their Bundle Revisions. This technique makes it possible to depict fragments
where a capability in the fragment is actually available from the host's Bundle Wiring.
Bundle Wire
Bundle Bundle
declaration bundle wiring declaration
Wiring Wiring
part part
Requirement
getRequirerWiring() <<interface>> getProviderWiring()
Capability
Bundle Wire
getRequirement() getCapability()
BundleWiring objects can continue to exist and operate as long as there are wires from other
BundleWiring objects, even after a bundle is updated. The only way to break this non-current wiring
is to refresh the bundles that are involved. The refresh operation computes a transitive closure of all
dependent bundles, and re-resolves them. Any active bundles in this closure will be stopped and
restarted. This operation can be activated on the Framework Wiring.
The wiring API is based on the Bundle.adapt() method, see Adaptations on page 123. This method al-
lows the Bundle object to be adapted to another type. For example:
For this API, the following adaptations of the Bundle object are supported:
• BundleRevision - Provides access to the current revision at the time of the adapt method call. A
Bundle will always have a current Bundle Revision until it is uninstalled.
• BundleWiring - Provides access to the current Bundle Wiring at the time of the adapt method call.
A current Bundle Wiring object only exists (the adapt method returns non-null) when the bundle
is resolved.
• BundleRevisions - Provides access to all the BundleRevision objects that are still in use. A Bundle
always has a BundleRevisions object, the adapt method must never return null.
• FrameworkWiring - Can only be adapted from the system bundle with bundle id 0. Provides ac-
cess to the management methods like refresh and resolve, and information about bundles that
are pending removal, and the dependency closure of a set of bundles.
The Bundle Wiring API is usable during launching after the init method has returned.
After an uninstall the adapt method will always return null for BundleRevision or BundleWiring.
However, it is possible that the Bundle Revision and/or its Bundle Wiring are reachable through oth-
er bundles.
Import-Package: com.acme.foo;version=1
Export-Package: com.acme.foo;version=1
Package Requirement
com.acme.foo;v1 com.acme.foo;v1
Package Capability
The following code prints the bundles that bundle A is wired to through Import-Package state-
ments:
.getBundle());
System.out.println(pack + " - " + bundle.getLocation());
}
}
<<interface>>
Bundle
Install/Update/Uninstall
<<interface>> <<interface>>
Bundle Bundle
Revision Revision
Resolve/Unresolve
<<interface>> <<interface>>
Bundle Wiring Bundle Wiring
in use current
The framework never eagerly disconnects the wires between Bundle Wirings,
a disconnect happens only under control of the management agent when the
refreshBundles(Collection,FrameworkListener...) method is called or when all requiring bun-
dles become uninstalled. When a bundle is updated, its existing BundleWiring objects will con-
tinue to serve classes and resources to bundles that use it. The update, even though it provides
a new revision, has no effect on resolved bundles with respect to class loading. Also, the instal-
lation of a new bundle could allow new wires but they must not affect the existing wiring until
refreshBundles(Collection,FrameworkListener...) is called (with the exception for dynamic im-
ports). Though the class loading wires remain in place, proper bundles should react to the changes
in the dynamic state. That is, when a bundle is updated it will be stopped, allowing others to remove
any references they have to that bundle. However, even in those cases the wirings will remain until
the bundle is unresolved during a refresh cycle.
After an update, the existing Bundle Wiring is no longer current for the bundle.
Bundle Wirings that are not in use (no other Bundle Wiring is wired to it) can be removed imme-
diately but in-use Bundle Wirings must remain in place until they become no longer in use. These
non-current in-use Bundle Wirings are called pending for removal.
To forcefully remove all these non-current in use Bundle Wirings the framework can refresh a set of
bundles at the request of a management agent. The refresh will create a transitive dependency graph
on an initial set of bundles and then unresolves each bundle in the graph, which will make any of
the stale Bundle Wirings no longer in use so they can be cleaned up. After this refresh, any previous-
ly active bundles will be restored to their previous state.
The purpose of this non-eager behavior is to allow for efficient handling of multiple updates/in-
stalls/uninstalls. Refreshing the wires after each such event requires the start and stop of the depen-
dent bundles, disrupting the operations of the system unnecessary often. It is therefore better to
batch up a number of such operations and then refresh the system once. However, the implication of
this optimization is that the actual wiring between bundles can quickly become an intricate web of
connections between revisions of bundles.
For example, assume a bundle A is installed. At installation, it will have a single Bundle Revision,
called A.0. Next, bundle B is installed, it will have a Bundle Revision B.0. Assuming Bundle Revision
A.0 requires a capability in bundle B, resolving bundle A and bundle B will create a Bundle Wiring
for Bundle Revision A.0 linking to a Bundle Wiring for Bundle Revision B.0. If bundle B is now up-
dated, it will create a second Bundle Revision, B.1.However, the current Bundle Wiring for bundle A
(Bundle Revision A.0) will remain wired to Bundle Revision B.0 as long as bundle A and bundle B re-
main resolved, even though the current Bundle Revision for bundle B has now become B.1. As long
as Bundle Revision A.0 remains resolved, bundle B's resolved state has no impact.
Bundles are only actually unresolved when they are refreshed, the UNRESOLVED event only indicates
that a Bundle is updated or uninstalled. Refreshing happens on a per bundle basis but takes any Bun-
dle Wirings into account that depend on the refreshed bundle. In the previous example, if bundle B
is refreshed, it will automatically refresh bundle A because A is wired to B. That is, bundle B is in use
by A. The refresh will stop bundles A and B and then unresolve both of them. Unresolving basical-
ly means removing any reference from the framework to the Bundle Wirings of the involved bun-
dles. This unreferencing will allow the garbage collector to remove any remains, like for example
the class loader and the activator, unless some bundles illegally hold on to references. Once a Bun-
dle Wiring is no longer required by the framework, it is set to be not in use, regardless of stale refer-
ences.
Normally, after unresolving, the bundles are started again in their original state, forcing them to re-
solve again. In the previous example, Bundle Revision A.0 will then be connected to the Bundle Revi-
sion B.1 through newly created BundleWiring objects. The old Bundle Wiring for B.0 will no longer
be in use and will thus be garbage collected.
This example is depicted in Figure 7.5. This picture shows when the different objects are created and
discarded. In this picture bundle B is not started.
Figure 7.5 The Bundle Revisions and Bundle Wirings over time
Install B
Resolve A,B
t
Update B
Refresh A,B
Resolve A,B
Uninstall B
Refresh
Bundle In use, not current Bundle Revision
current & in use Bundle Wiring
Bundle Revision
Wire
The resolver is responsible for wiring Bundle Requirements and Bundle Capabilities to each other
while adhering to the semantics defined in their namespace. For each paired Bundle Requirement
and Bundle Capability the resolver creates a Bundle Wire that links the Bundle Requirement, the re-
quiring Bundle Wiring, the providing Bundle Wiring, and the Bundle Capability. The relationships
between a bundle A and bundle B, where A requires some capability in B, is depicted in Figure 7.6.
Bundle A Bundle B
Bundle Bundle
Revision Revision
A.0 B.0
Wire
The OSGi framework can add wires and new requirements and capabilities after resolving during
run time. This mechanism is for example used in DynamicImport-Package, dynamic attaching of
fragments, and byte code weaving.
7.4 Fragments
The type of a bundle is available on the Bundle Revision because a Bundle can change from a frag-
ment to a normal bundle or vice versa after an update. The getTypes() method is used to obtain a
bitmap that is either 0 or has the following bit set:
The type is a bitmap allowing future versions of this specification to add new types that can be a
combination of existing and new types. The following example displays how a Bundle is checked to
be a fragment:
A fragment bundle will show all its declared capabilities and requirements on its Bundle Revision
but during resolving the resolver only considers the osgi.wiring.host and osgi.ee requirements and
the osgi.identity capability and requirements.
The osgi.wiring.host requirement represents the Fragment-Host header. A fragment can be attached
to different hosts and each attachment creates a wire from the fragment's Bundle Wiring to the
host's Bundle Wiring. The osgi.ee requirement is also never hosted.
The osgi.identity capability of a fragment is part of the fragment's Bundle Wiring and is not part of
a host bundle's Bundle Wiring. That is, each Bundle Wiring has exactly one osgi.identity capability.
However, osgi.identity requirements declared by a fragment are not part of the fragment's Bundle
Wiring and are instead hosted by the host bundle's Bundle Wiring.
Any other requirements and capabilities in a fragment bundle never become part of the fragment's
Bundle Wiring; they are treated as part of the host's requirements and capabilities when the frag-
ment is attached to that host.
To find the attached fragment for a host bundle it is necessary to find the wires for the
osgi.wiring.host capability. The requiring end of such a wire is the attached fragment and the pro-
viding end is the attaching host.
For example, bundle A is a host and bundle B is a fragment as depicted in Figure 7.7 on page 165.
hosts =
getRequiredWires("osgi.wiring.host")
It is also possible to calculate the reverse dependency for finding the hosts of a fragment. For the pre-
vious example, the bundles that attach fragment B can be found with:
The osgi.wiring.host namespace mandates that the resolver moves the Bundle Requirements
and Bundle Capabilities from the fragment in all other namespaces than the osgi.wiring.host,
osgi.identity and osgi.ee namespaces to the host bundle. For example, if the fragment exports a
package p, then this package is exported by the host. In such a case, the BundleRequirement and
BundleCapability objects remain associated with the Bundle Revision of the fragment. However, the
Bundle Wire has the appropriate Bundle Wiring of the host. This is depicted in Figure 7.8 on page
165. Package p is declared a capability in fragment B.0 but when wired the Bundle Wiring of host
A.0 will be the provider.
p C.0
The previous example is also depicted as an instance diagram in Figure 7.9 on page 166.
bundle wire
Bundle Wiring
C.0 declared wire
Bundle
Revision
C.0
FrameworkWiring fw = systemBundle.adapt(FrameworkWiring.class);
7.5.1 Refreshing
The update of bundles will create new Bundle Revisions while the existing Bundle Wirings re-
main wired to their previous Bundle Revisions. This stale wiring must be cleaned up and the
refreshBundles(Collection,FrameworkListener...) method achieves this.
The refreshBundles method works from an initial collection of bundles that is used to seed the cal-
culation of the dependency closure. The dependency closure is calculated by expanding the seed de-
pendency closure to include any bundle that has a Bundle Wiring that depends on any bundle in
the dependency closure. This is a recursive definition so the dependency closure contains the list of
transitive dependencies on the initial seed collection.
This dependency closure can be obtained separately with the getDependencyClosure(Collection)
method providing it with the same seed. If no seed is provided, that is a null argument is given, the
refreshBundles method will be identical to calling it with the result of the getRemovalPendingBun-
dles() method as the seed collection. This default will ensure that all stale Bundle Wirings will be
cleaned up.
The refresh process will stop any bundles in the considered collection while recording their state
and, if active, their starting option (for example START_TRANSIENT). Stopping must take any start
level rules into account.
The refresh must then unresolve all the bundles in the considered collection. Unresolving will cause
all the removal pending Bundle Wirings to become no longer in use because there are no longer any
bundles requiring them. This will make the Bundle Wirings available for garbage collection because
they are then no longer reachable from the framework API.
The framework must then attempt to restore the state as it was before the refresh taking all the
framework rules into account, including start levels, start options, and activation options.
The actual refresh operation will take place in the background because it can be a long running op-
eration. The refresh operation will send out a global framework event PACKAGES_REFRESHED. How-
ever, catching this event properly is non-trivial. For this reason, the refreshBundle method also al-
lows a callback by specifying an optional Framework Listener in the method invocation that will
only be called when the method is finished. For example:
• Bundle Class Path Order - Scan the bundle class path containers.
• Entry Order - Scan all the entries that constitute a bundle and its attached fragments.
META-INF/versions/9/com/foo/resource.txt
and the call listResources(“/com/foo”, “*.txt”, 0) is made when running on Java 9, or later, the re-
sult must include
com/foo/resource.txt
The listResources(String,String,int) method has no counterpart in the standard class loader API.
7.7 Security
The Bundle Wiring API requires Adapt Permission with action ADAPT for the following types:
• org.osgi.framework.wiring.BundleWiring
• org.osgi.framework.wiring.BundleRevision
• org.osgi.framework.wiring.BundleRevisions
• org.osgi.framework.wiring.FrameworkWiring
The Framework Wiring methods that mutate state require an additional Admin Permission with the
action:
7.8 Changes
• Added support for multi-release JARs. See Bundle Class Path Order on page 168.
8 Framework Namespaces
Specification
Version 1.1
8.1 Introduction
A key aspect of the OSGi dependency model based on requirements and capabilities is the concept
of a namespace. A Namespace defines the semantics of a Requirement-Capability pair. This generic
model is defined in Resource API Specification on page 151. This section defines a number of name-
spaces that are part of the OSGi Core specification. The osgi.wiring.* namespaces map to the mod-
ule layer, others are used as foundations for other specifications.
Namespaces that are mapped from OSGi manifest headers must never be specified as generic re-
quirements or capabilities in the manifest. The purpose of these namespaces is only to provide the
Modularity manifest headers in generic form; the framework must translate the specific manifest
headers defined in the Module Layer on page 33 to their generic form so that requirements and capa-
bilities can be used in a uniform way, regardless if they originate from specialized or generic mani-
fest headers.
Each namespace is defined with the following items:
Attributes on manifest headers that define capabilities are used as matching attributes in the
requirement's filter and are available as the attributes of a Capability object. Attributes on manifest
headers that define requirements are translated to a conjunction of assertions in the filter that cor-
respond to the semantics of their header. That is, these attributes on requiring manifest headers are
not visible on the Requirement objects as attributes.
Unless an attribute is specifically overridden, all namespaces inherit the attributes and directives of
the default namespace as defined in Table 8.1 and in Namespace.
Namespaces can have any additional attributes and directives, both defined in a namespace as well
as ad-hoc. However, none of these additional directives or attributes must require different or addi-
tional matching rules.
All directives and attributes specified on the OSGi manifest headers that are translated to require-
ments and capabilities are visible in these capabilities and requirements, except when they are
specifically noted to be ignored in the definition of a namespace.
Provide-Capability: «
osgi.ee; «
osgi.ee="OSGi/Minimum"; «
version:List<Version>="1.0,1.1,1.2", «
osgi.ee; «
osgi.ee="JavaSE"; «
version:List<Version>="1.2,1.3,1.4,1.5,1.6"
Bundles can require the osgi.ee capability if they have a dependency on a specific execution envi-
ronment, for example:
Require-Capability: «
osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))"
This is useful when the bundle contains class files compiled to target a version of the Java VM and
thus cannot be loaded by prior versions of the Java VM. If a bundle needs to require that specific ja-
va.* packages are available in the runtime, it should use the Import-Package header to require those
packages. See Execution Environment on page 48.
The osgi.ee requirement is not hosted when it is part of a Fragment. That is, a requirement from this
namespace must be treated as part of the Fragment Bundle and must not be hosted.
The osgi.ee capability is defined in table Table 8.2 and in the ExecutionEnvironmentNamespace
class.
Table 8.2 osgi.ee Namespace definition
Name Kind M/O Type Syntax Description
osgi.ee CA M String ~(ws|',')+ The name of the execution environment. The
name can contain any character except white
space (as defined by Java) or the comma (','
\u002C) character.
version CA M List version ( ',' version )* A comma separated list of versions, compar-
isons must be done with version ordering be-
<Version>
cause the version attribute must be declared
with the List<Version> type.
Provide-Capability headers in the osgi.ee namespace must not be used in a bundle's manifest; Re-
quire-Capability with this namespace is allowed. An osgi.ee requirement is the replacement for the
Bundle-RequiredExecutionEnvironment header in Bundle-RequiredExecutionEnvironment on page 48.
The names for the execution environments are not normatively defined in this specification except
those defined in Table 8.3. A list of well-known (non-normative) names are maintained at [1] Specifi-
cation References.
Table 8.3 osgi.ee execution environment names
Name Description
JavaSE Should be used for all Java SE execution environments since Java 1.2. The name
for the Java Runtime Environment has changed several times but for all envi-
ronments the Java SE name must be used.
JavaSE/compact1 Java SE Embedded compact1 profile.
JavaSE/compact2 Java SE Embedded compact2 profile.
JavaSE/compact3 Java SE Embedded compact3 profile.
OSGi/Minimum The OSGi Minimum execution environment.
Bundle A:
Import-Package: p
DynamicImport-Package: q.*
Bundle B:
Export-Package: p
This example is depicted in Figure 8.1. Package p is wired to a Bundle Revision of bundle B because it
exports package p. The DynamicImport-Package clause is not wired but this can change when dur-
ing run time package s refers to a class that cannot be found.
Figure 8.1 Example osgi.wiring.package Namespace
A p p B
q.* dynamic
s
The osgi.wiring.package attributes are defined in Table 8.4 and in the PackageNamespace class.
Table 8.4 osgi.wiring.package Namespace definition
Name Kind M/O Type Syntax Description
osgi.wiring.package CA M String package-name The name of the package.
version CA M Version version A version of the exported package
bundle-symbolic-name CA M String symbolic-name The bundle symbolic name of the bundle
that exports the package
bundle-version CA M Version version The bundle version as defined in the Bun-
dle-Version header.
* CA O String * Any attributes defined on the Export-Pack-
age clause
resolution RD O String 'dynamic' | This directive is inherited from the default
namespace but this namespace adds an ad-
'mandatory' |
ditional value dynamic.
'optional'
The following directives must be ignored when specified on the Import-Package, or Export-Package,
or DynamicImport-Package manifest headers:
• effective
• cardinality
The requirements and capabilities in the osgi.wiring.package namespace must never be used in the
Require-Capability and Provide-Capability headers.
The effect of the osgi.wiring.bundle namespace is that the exported packages of any required bun-
dles become available to the requirer as defined in the Requiring Bundles on page 84. A Bundle Wire
in the osgi.wiring.bundle namespace does not imply the availability of osgi.wiring.package Bundle
Wires that correspond to the required bundle's exported packages. If there is a need to know what
packages will become available then this must be deduced from the osgi.wiring.package capabilities
of the required bundle.
The following directives must be ignored when specified on the Require-Bundle or Bundle-Symbol-
icName manifest headers:
• uses
• effective
• cardinality
The requirements and capabilities in the osgi.wiring.bundle namespace must not be used in the Re-
quire-Capability and Provide-Capability headers.
The effect of the osgi.wiring.host namespace is that all declared capabilities and requirements of the
fragment, except the osgi.wiring.host and osgi.ee requirements and the osgi.identity capability, are
merged with the host bundle as defined in the Fragment Bundles on page 87.
The following directives must be ignored when specified on the Fragment-Host or Bundle-Symbolic-
Name manifest headers:
• uses
• effective
• cardinality
The requirements and capabilities in the osgi.wiring.host namespace must not be used in the Re-
quire-Capability and Provide-Capability headers.
Provide-Capability headers in the osgi.identity Namespace must not be used in the manifest, Re-
quire-Capability with this Namespace is allowed.
A resource can specify a relation to other resource by declaring an optional requirement to that oth-
er resource. Such relation requirements should be placed in another effective time than resolve to
not interfere with resolving, for example the effective time meta. The requirements should be in to
the osgi.identity namespace and assert:
The requirement must then add a directive classifier that defines the related type so that tools like
IDEs can find the relations by iteration over all the osgi.identity requirements that have a classifier
directive. In general, these requirement should be optional and have a cardinality of single.
The following values are defined for the classifier directive:
• sources - An archive containing the source code in the same directory layout as this resource.
• javadoc - An archive containing the Javadoc in the same directory layout as this resource
• * - Any other names
For example, a bundle could contain the following requirement modeling a relation:
Require-Capability: «
osgi.identity; «
filter:="(&(osgi.identity=org.example.foo-source)(version=1.1))"; «
effective:=meta; «
classifier:=sources; «
resolution:=optional
if ( caps==null || caps.isEmpty())
continue;
Capability c = caps.iterator().next();
Resource related = c.getResource();
return ((RepositoryContent)related).getContent();
}
}
return null;
}
pability is provided when running a 64-bit VM on a Windows 7 machine with the language set to
en_US:
Provide-Capability: «
osgi.native; «
osgi.native.osname:List<String>="Windows7,Windows 7,Win7,Win32"; «
osgi.native.osversion:Version="7.0"; «
osgi.native.processor:List<String>="x86-64,amd64,em64t,x86_64"; «
osgi.native.language="en"
Provide-Capability headers in the osgi.native namespace must not be used in a bundle's manifest.
Bundles can require an osgi.native capability which matches the native environment required for
the bundle to function properly, for example:
Require-Capability: «
osgi.native; «
filter:=" «
(& «
(osgi.native.osname~=win32) «
(osgi.native.processor~=x86-64) «
(osgi.native.language~=en) «
)"
The osgi.native namespace is not used to specify native code paths packaged within a bundle. The
Bundle-NativeCode header is used to specify native code paths. The OSGi Framework converts a
Bundle-NativeCode into an osgi.native requirement which describes the native environment re-
quired to execute native code packaged within a Bundle (see Loading Native Code Libraries on page
76). There is no need for a bundle to specify both a Bundle-NativeCode header and an osgi.native re-
quirement.
Native code included in a Fragment Bundle gets loaded by the class loaders of the Host Bundles the
Fragment is attached to, therefore the osgi.native requirement is hosted when it is part of a Frag-
ment. That is, a requirement from this namespace must be treated as part of the Host Bundles the
Fragment is attached to.
The osgi.native capability is defined in table Table 8.8 and in the NativeNamespace class.
Table 8.8 osgi.native Namespace definition
Name Kind M/O Type Syntax Description
osgi.native.osname CA M List osname A comma separated list of canonical os name
aliases to the org.osgi.framework.os.name
<String> ( ',' osname )*
launching property value (See Table 4.3 and
[11] OSGi Reference Names). For example,
an org.osgi.framework.os.name value of
Windows95 will get a List<String> value of
Windows95,Windows 95,Win95,Win32
osgi.native.osversion CA M Version version A Version as parsed from the value of the
org.osgi.framework.os.version launching
property
osgi.native.processor CA M List processor A comma separated list of canon-
ical processor aliases to the
<String> ( ',' processor )*
org.osgi.framework.processor launch-
ing property value (See Table 4.2 and
[11] OSGi Reference Names). For example,
an org.osgi.framework.processor val-
ue of x86 will get a List<String> value of
x86,pentium,i386,i486,i586,i686
In addition to the attributes defined in Table 8.8 an OSGi Framework must populate the osgi.native
capability attributes with the values included in the Framework launching properties (see Launch-
ing Properties on page 102). Launching property keys that start with osgi.native. are excluded to pre-
vent collisions with the defined capability attribute keys.
8.8 References
[1] Specification References
https://www.osgi.org/developer/specifications/reference/
8.9 Changes
• Added osgi.ee capability names for Java SE Embedded compact profiles in osgi.ee Namespace on
page 172.
• Updated osgi.ee description to indicate that bundles should import the java.* packages they re-
quire to ensure the runtime provides them.
9.1 Introduction
This specification describes how to enable a management agent to control the relative starting and
stopping order of bundles in an OSGi framework.
The management agent can set the start levels for bundles and set the active start level of the Frame-
work, which will start and stop the appropriate bundles. Only bundles that have a start level less or
equal to this active start level must be active. The purpose of the Start Level API is to allow the man-
agement agent to control, in detail, what bundles will be started and stopped and when this occurs.
9.1.1 Essentials
• Ordering - A management agent should be able to order the startup and shutdown sequences of
bundles.
• Levels - The management agent should support a virtually unlimited number of levels.
9.1.2 Entities
• Bundle Start Level - The adapter on a bundle that is used by a management agent to order the start-
up and shutdown sequences of bundles.
• Framework Start Level - The adapter that is used to set the framework start levels.
• Management Agent - A bundle that is provided by the Operator to implement an Operator specific
policy.
• Framework Event - See Events on page 127.
• Framework Listener - See Listeners on page 127.
1
adapt
0..1 0..1
<<interface>> <<interface>>
Bundle Start Framework
Level Start Level
Defining the order in which bundles are started and stopped is useful for the following:
• Safe mode - The management agent can implement a safe mode. In this mode, only fully trusted
bundles are started. Safe mode might be necessary when a bundle causes a failure at startup that
disrupts normal operation and prevents correction of the problem.
• Splash screen - If the total startup time is long, it might be desirable to show a splash screen dur-
ing initialization. This improves the user's perception of the boot time of the device. The startup
ordering can ensure that the right bundle is started first.
• Handling erratic bundles - Problems can occur because bundles require services to be available
when they are activated (this is a programming error). By controlling the start order, the manage-
ment agent can prevent these problems.
• High priority bundles - Certain tasks such as metering need to run as quickly as possible and can-
not have a long startup delay. These bundles can be started first.
Start levels are not intended to be used for ensuring that dependencies are met when a bundle is
started. Any of the life cycle actions (install/update/uninstall) can cause a dependency to become
unavailable regardless of start levels.
9.2.1 Adaptations
This specification provides two adaptations of a Bundle object to a:
• BundleStartLevel - Used to get and set the start level on a specific bundle.
• FrameworkStartLevel - Used to get and control the framework start level. This adaptation must
return null for any other bundle than the system bundle (bundle 0).
• setStartLevel(int) - Sets the current start level for the adapted bundle.
• getStartLevel() - Gets the current start level for the adapted bundle.
• isActivationPolicyUsed() - Answer if the activation policy is used.
• isPersistentlyStarted() - Answer if this bundle as persistently started.
• getInitialBundleStartLevel() - Return the start level to assign for newly installed bundles.
• setInitialBundleStartLevel(int) - Set the initial start level.
• getStartLevel() - Get the current framework start level.
• setStartLevel(int,FrameworkListener...) - Set the current framework start level and provide an
optional callback Framework Listener. This listener is called back when the set start level has
been reached.
ered equivalent). In this state, no bundles are running. Progressively higher integral values represent
progressively higher start levels. For example, 2 is a higher start level than 1. The Framework must
support all positive int values (Integer.MAX_VALUE) for start levels.
The Framework has an active start level that is used to decide which bundles can be started. All bun-
dles must be assigned a bundle start level. This is the minimum start level to start a bundle. The bun-
dle start level can be set with the setStartLevel(int) method on the BundleStartLevel object. When
a bundle is installed, it is initially assigned the bundle start level returned by getInitialBundleS-
tartLevel() on a FrameworkStartLevel object. The initial bundle start level to be used when bundles
are installed can be set with setInitialBundleStartLevel(int).
In addition, a bundle can be persistently marked as started or stopped with the Bundle start and stop
methods. A bundle cannot run unless it is marked started, regardless of the bundle's start level.
The Framework continues increasing the active start level and starting the appropriate bundles un-
til it has started all bundles with a bundle start level that equals the requested start level.
The Framework must not increase to the next active start level until all started bundles
have returned from their BundleActivator.start method normally or with an exception. A
FrameworkEvent.ERROR must be broadcast when the BundleActivator.start method throws an ex-
ception.
If the requested start level is lower than the active start level, the Framework must stop all bun-
dles that have a bundle start level that is equal to the active start level. The Framework must then
decrease the active start level by 1. If the active start level is still higher than the requested start
level, it should continue stopping the appropriate bundles and decreasing the active start level
until the requested start level is reached. A FrameworkEvent.ERROR must be broadcast when the
BundleActivator.stop method throws an exception.
If the requested start level is the active start level, the Framework will not start or stop any bundles.
When the requested start level is reached and all bundles satisfy the condition
that their bundle start level <= active start level in order to be started, then the
FrameworkEvent.STARTLEVEL_CHANGED event must be sent to all registered FrameworkListener
objects. If the requested start level and active start level are equal, then this event may arrive before
the setStartLevel method has returned.
It must therefore always be true that:
• A bundle is started, or will be started soon, if the start level is less or equal to the active start level.
• A bundle is stopped, or will be stopped soon, when it has a start level more than the active start
level.
move to R
A<R A>R
publish event
A==R
If the Framework is currently involved in changing the active start level, it must first reach the pre-
viously requested start level before it is allowed to continue with a newly requested start level. For
example, assume the active start level is 5 and the Framework is requested to transition to start level
3. Before start level 3 is reached, another request is made to transition to start level 7. In this case, the
OSGi Framework must first complete the transition to start level 3 before it transitions to start level
7.
must compare the new bundle start level to the active start level. For example, assume that the ac-
tive start level is 5 and a bundle with start level 5 is started. If the bundle's start level subsequently is
changed to 6 then this bundle must be stopped by the OSGi Framework but it must still be marked
persistently to be started.
Screen screen;
public void start(BundleContext context) {
context.addFrameworkListener( this );
screen = createSplash();
screen.open();
}
public void stop(BundleContext context) {
screen.close();
}
public void frameworkEvent( FrameworkEvent event ) {
if ( event.getType() == FrameworkEvent.STARTED )
screen.close();
}
Screen createSplash() { ... }
}
9.5 Security
The Start Level API requires Adapt Permission with action ADAPT for the following type:
• org.osgi.framework.startlevel.BundleStartLevel
• org.osgi.framework.startlevel.FrameworkStartLevel
The Start Level methods that mutate state require an additional Admin Permission with the action:
• EXECUTE - For bundles that must be able to modify a bundle's start level
• STARTLEVEL - For modifying the Framework's active start level.
10 Framework API
10.1 org.osgi.framework
Framework Package Version 1.9.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework; version="[1.9,2.0)"
10.1.1 Summary
• AdaptPermission - A bundle's authority to adapt an object to a type.
• AdminPermission - A bundle's authority to perform specific privileged administrative opera-
tions on or to get sensitive information about a bundle.
• AllServiceListener - A ServiceEvent listener that does not filter based upon package wiring.
• Bundle - An installed bundle in the Framework.
• BundleActivator - Customizes the starting and stopping of a bundle.
• BundleContext - A bundle's execution context within the Framework.
• BundleEvent - An event from the Framework describing a bundle lifecycle change.
• BundleException - A Framework exception used to indicate that a bundle lifecycle problem oc-
curred.
• BundleListener - A BundleEvent listener.
• BundlePermission - A bundle's authority to require or provide a bundle or to receive or attach
fragments.
• BundleReference - A reference to a Bundle.
• CapabilityPermission - A bundle's authority to provide or require a capability.
• Configurable - Supports a configuration object.
• Constants - Defines standard names for the OSGi environment system properties, service prop-
erties, and Manifest header attribute keys.
• Filter - An RFC 1960 [http://www.ietf.org/rfc/rfc1960.txt]-based Filter.
• FrameworkEvent - A general event from the Framework.
• FrameworkListener - A FrameworkEvent listener.
• FrameworkUtil - Framework Utility class.
• InvalidSyntaxException - A Framework exception used to indicate that a filter string has an in-
valid syntax.
• PackagePermission - A bundle's authority to import or export a package.
• PrototypeServiceFactory - A factory for prototype scope services.
• ServiceEvent - An event from the Framework describing a service lifecycle change.
• ServiceException - A service exception used to indicate that a service problem occurred.
• ServiceFactory - A factory for bundle scope services.
• ServiceListener - A ServiceEvent listener.
• ServiceObjects - Allows multiple service objects for a service to be obtained.
• ServicePermission - A bundle's authority to register or get a service.
(adaptClass=com.acme.*)
(&(signer=\*,o=ACME,c=US)(adaptClass=com.acme.*))
(signer=\*,o=ACME,c=US)
When a signer key is used within the filter expression the signer value must escape the special filter
chars ('*', '(', ')').
The name is specified as a filter expression. The filter gives access to the following attributes:
• signer - A Distinguished Name chain used to sign the exporting bundle. Wildcards in a DN are
not matched according to the filter string rules, but according to the rules defined for a DN chain.
• location - The location of the exporting bundle.
• id - The bundle ID of the exporting bundle.
• name - The symbolic name of the exporting bundle.
• adaptClass - The name of the type to which an object can be adapted.
□ Creates a new requested AdaptPermission object to be used by the code that must perform checkPer-
mission. AdaptPermission objects created with this constructor cannot be added to an AdaptPermis-
sion permission collection.
Returns true if the specified permission is implied by this object; false otherwise.
Action Methods
class Bundle.loadClass
execute Bundle.start
Bundle.stop
BundleStartLevel.setStartLevel
extensionLifecycle BundleContext.installBundle for extension bundles
Bundle.update for extension bundles
Bundle.uninstall for extension bundles
lifecycle BundleContext.installBundle
Bundle.update
Bundle.uninstall
listener BundleContext.addBundleListener for
SynchronousBundleListener
BundleContext.removeBundleListener for
SynchronousBundleListener
metadata Bundle.getHeaders
Bundle.getLocation
resolve FrameworkWiring.refreshBundles
FrameworkWiring.resolveBundles
resource Bundle.getResource
Bundle.getResources
Bundle.getEntry
Bundle.getEntryPaths
Bundle.findEntries
Bundle resource/entry URL creation
startlevel FrameworkStartLevel.setStartLevel
FrameworkStartLevel.setInitialBundleStartLevel
context Bundle.getBundleContext
weave WovenClass.getBytes
WovenClass.setBytes
WovenClass.getDynamicImports for modification
The special action "*" will represent all actions. The resolve action is implied by the class, execute
and resource actions.
The name of this permission is a filter expression. The filter gives access to the following attributes:
• signer - A Distinguished Name chain used to sign a bundle. Wildcards in a DN are not matched
according to the filter string rules, but according to the rules defined for a DN chain.
• location - The location of a bundle.
• id - The bundle ID of the designated bundle.
• name - The symbolic name of a bundle.
(signer=\*,o=ACME,c=US)
(&(signer=\*,o=ACME,c=US)(name=com.acme.*)
(location=http://www.acme.com/bundles/*))
(id>=1)
When a signer key is used within the filter expression the signer value must escape the special filter
chars ('*', '(', ')').
• this object's filter matches the specified permission's bundle ID, bundle symbolic name, bundle
location and bundle signer distinguished name chain OR
• this object's filter is "*"
AND this object's actions include all of the specified permission's actions.
Special case: if the specified permission was constructed with "*" filter, then this method returns
true if this object's filter is "*" and this object's actions include all of the specified permission's ac-
tions
Returns true if the specified permission is implied by this object; false otherwise.
• UNINSTALLED
• INSTALLED
• RESOLVED
• STARTING
• STOPPING
• ACTIVE
Values assigned to these states have no specified ordering; they represent bit values that may be
ORed together to determine if a bundle is in one of the valid states.
A bundle should only have active threads of execution when its state is one of STARTING,ACTIVE, or
STOPPING. An UNINSTALLED bundle can not be set to another state; it is a zombie and can only be
reached because references are kept somewhere.
The Framework is the only entity that is allowed to create Bundle objects, and these objects are only
valid within the Framework that created them.
Bundles have a natural ordering such that if two Bundles have the same bundle id they are equal. A
Bundle is less than another Bundle if it has a lower bundle id and is greater if it has a higher bundle
id.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
Note that the bundle is not active yet. A bundle must be put in the RESOLVED state before it can be
started. The Framework may attempt to resolve a bundle at any time.
The value of RESOLVED is 0x00000004.
This bit may be set when calling start(int) to notify the framework that the bundle must be activat-
ed using the bundle's declared activation policy.
See Also Constants.BUNDLE_ACTIVATIONPOLICY, start(int)
Since 1.4
URLs for directory entries must have their path end with "/".
Note: Jar and zip files are not required to include directory entries. URLs to directory entries will not
be returned if the bundle contents do not contain directory entries.
Returns An enumeration of URL objects for each matching entry, or null if no matching entry could be found
or if the caller does not have the appropriate AdminPermission[this,RESOURCE], and the Java Run-
time Environment supports permissions. The URLs are sorted such that entries from this bundle are
returned first followed by the entries from attached fragments in attachment order. If this bundle is
a fragment, then only matching entries in this fragment are returned.
Throws IllegalStateException– If this bundle has been uninstalled.
Since 1.3
This method must continue to return this bundle's unique identifier while this bundle is in the
UNINSTALLED state.
Returns The unique identifier of this bundle.
Bundle-Name
Bundle-Vendor
Bundle-Version
Bundle-Description
Bundle-DocURL
Bundle-ContactAddress
This method must continue to return Manifest header information while this bundle is in the
UNINSTALLED state.
Returns An unmodifiable Dictionary object containing this bundle's Manifest headers and values.
Throws SecurityException– If the caller does not have the appropriate AdminPermission[this,METADATA],
and the Java Runtime Environment supports permissions.
See Also Constants.BUNDLE_LOCALIZATION
Where bn is this bundle's localization basename, Ls, Cs and Vs are the specified locale (language,
country, variant) and Ld, Cd and Vd are the default locale (language, country, variant). If null is spec-
ified as the locale string, the header values must be localized using the default locale. If the empty
string ("") is specified as the locale string, the header values must not be localized and the raw (unlo-
calized) header values, including any leading "%", must be returned. If no localization is found for a
header value, the header value without the leading "%" is returned.
This method must continue to return Manifest header information while this bundle is in the
UNINSTALLED state, however the header values must only be available in the raw and default locale
values.
Returns An unmodifiable Dictionary object containing this bundle's Manifest headers and values.
Throws SecurityException– If the caller does not have the appropriate AdminPermission[this,METADATA],
and the Java Runtime Environment supports permissions.
See Also getHeaders(), Constants.BUNDLE_LOCALIZATION
Since 1.3
solved, then only this bundle must be searched for the specified resources. Imported packages can-
not be searched when a bundle has not been resolved. If this bundle is a fragment bundle then null is
returned.
Note: Jar and zip files are not required to include directory entries. URLs to directory entries will not
be returned if the bundle contents do not contain directory entries.
Returns An enumeration of URLs to the named resources, or null if the resource could not be
found or if this bundle is a fragment bundle or if the caller does not have the appropriate
AdminPermission[this,RESOURCE], and the Java Runtime Environment supports permissions.
Throws IllegalStateException– If this bundle has been uninstalled.
IOException– If there is an I/O error.
Since 1.3
Throws ClassNotFoundException– If no such class can be found or if this bundle is a fragment bundle or if
the caller does not have the appropriate AdminPermission[this,CLASS], and the Java Runtime Envi-
ronment supports permissions.
IllegalStateException– If this bundle has been uninstalled.
Since 1.3
• If the START_TRANSIENT option is set, then a BundleException is thrown indicating this bundle
cannot be started due to the Framework's current start level.
• Otherwise, the Framework must set this bundle's persistent autostart setting to Started with de-
clared activation if the START_ACTIVATION_POLICY option is set or Started with eager activation if
not set.
When the Framework's current start level becomes equal to or more than this bundle's start level,
this bundle will be started.
Otherwise, the following steps are required to start this bundle:
1. If this bundle is in the process of being activated or deactivated then this method must wait for
activation or deactivation to complete before continuing. If this does not occur in a reasonable
time, a BundleException is thrown to indicate this bundle was unable to be started.
2. If the START_TRANSIENT option is not set then set this bundle's autostart setting to Started with
declared activation if the START_ACTIVATION_POLICY option is set or Started with eager activa-
tion if not set. When the Framework is restarted and this bundle's autostart setting is not Stopped,
this bundle must be automatically started.
3. If this bundle's state is ACTIVE then this method returns immediately.
4. If this bundle's state is not RESOLVED, an attempt is made to resolve this bundle. If the Frame-
work cannot resolve this bundle, a BundleException is thrown.
5. If the START_ACTIVATION_POLICY option is set and this bundle's declared activation policy is
lazy then:
• If this bundle's state is STARTING then this method returns immediately.
• This bundle's state is set to STARTING.
• A bundle event of type BundleEvent.LAZY_ACTIVATION is fired.
• This method returns immediately and the remaining steps will be followed when this
bundle's activation is later triggered.
6. This bundle's state is set to STARTING.
7. A bundle event of type BundleEvent.STARTING is fired.
8. The BundleActivator.start(BundleContext) method of this bundle's BundleActivator, if one is
specified, is called. If the BundleActivator is invalid or throws an exception then:
• This bundle's state is set to STOPPING.
• A bundle event of type BundleEvent.STOPPING is fired.
• Any services registered by this bundle must be unregistered.
• Any services used by this bundle must be released.
• Any listeners registered by this bundle must be removed.
Preconditions
• Bundle autostart setting is modified unless the START_TRANSIENT option was set.
• getState() in { ACTIVE } unless the lazy activation policy was used.
• BundleActivator.start() has been called and did not throw an exception unless the lazy activa-
tion policy was used.
• Depending on when the exception occurred, bundle autostart setting is modified unless the
START_TRANSIENT option was set.
• getState() not in { STARTING, ACTIVE }.
Preconditions
• getState() in { ACTIVE }.
• Bundle autostart setting is modified unless the STOP_TRANSIENT option was set.
• getState() not in { ACTIVE, STOPPING }.
• BundleActivator.stop has been called and did not throw an exception.
• Bundle autostart setting is modified unless the STOP_TRANSIENT option was set.
IllegalStateException– If this bundle has been uninstalled or this bundle tries to change its own
state.
SecurityException– If the caller does not have the appropriate AdminPermission[this,EXECUTE],
and the Java Runtime Environment supports permissions.
See Also start(int)
Preconditions
• getState() in { UNINSTALLED }.
• This bundle has been uninstalled.
Throws BundleException– If the uninstall failed. This can occur if another thread is attempting to change
this bundle's state and does not complete in a timely manner. BundleException types thrown by this
method include: BundleException.STATECHANGE_ERROR
IllegalStateException– If this bundle has been uninstalled or this bundle tries to change its own
state.
SecurityException– If the caller does not have the appropriate AdminPermission[this,LIFECYCLE],
and the Java Runtime Environment supports permissions.
See Also stop()
bundle's original location. The input stream must always be closed when this method completes,
even if an exception is thrown.
□ Updates this bundle from an InputStream.
If the specified InputStream is null, the Framework must create the InputStream from which to read
the updated bundle by interpreting, in an implementation dependent manner, this bundle's Bun-
dle-UpdateLocation Manifest header, if present, or this bundle's original location.
If this bundle's state is ACTIVE, it must be stopped before the update and started after the update suc-
cessfully completes.
If this bundle has exported any packages that are imported by another bundle, these packages must
remain exported until the FrameworkWiring.refreshBundles method has been has been called or
the Framework is relaunched.
The following steps are required to update a bundle:
Preconditions
Throws BundleException– If this bundle could not be updated. BundleException types thrown by this
method include: BundleException.READ_ERROR, BundleException.DUPLICATE_BUNDLE_ERROR,
BundleException.MANIFEST_ERROR, BundleException.NATIVECODE_ERROR,
BundleException.RESOLVE_ERROR, BundleException.STATECHANGE_ERROR, and
BundleException.ACTIVATOR_ERROR.
IllegalStateException– If this bundle has been uninstalled or this bundle tries to change its own
state.
SecurityException– If the caller does not have the appropriate AdminPermission[this,LIFECYCLE]
for both the current bundle and the updated bundle, and the Java Runtime Environment supports
permissions.
See Also stop(), start()
This method must complete and return to its caller in a timely manner.
Throws Exception– If this method throws an exception, the bundle is still marked as stopped, and the
Framework will remove the bundle's listeners, unregister all services registered by the bundle, and
release all services used by the bundle.
A BundleContext object will be created for a bundle when the bundle is started. The Bundle object
associated with a BundleContext object is called the context bundle.
The BundleContext object will be passed to the BundleActivator.start(BundleContext) method
during activation of the context bundle. The same BundleContext object will be passed to the
BundleActivator.stop(BundleContext) method when the context bundle is stopped. A BundleCon-
text object is generally for the private use of its associated bundle and is not meant to be shared with
other bundles in the OSGi environment.
The BundleContext object is only valid during the execution of its context bundle; that is, during
the period from when the context bundle is in the STARTING, STOPPING, and ACTIVE bundle states.
However, the BundleContext object becomes invalid after BundleActivator.stop(BundleContext)
returns (if the bundle has a Bundle Activator). The BundleContext object becomes invalid be-
fore disposing of any remaining registered services and releasing any remaining services in use.
Since those activities can result in other bundles being called (for example, ServiceListeners for
ServiceEvent.UNREGISTERING events and ServiceFactorys for unget operations), those other bun-
dles can observe the stopping bundle in the STOPPING state but with an invalid BundleContext ob-
ject. If the BundleContext object is used after it has become invalid, an IllegalStateException must
be thrown. The BundleContext object must never be reused after its context bundle is stopped.
Two BundleContext objects are equal if they both refer to the same execution context of a bundle.
The Framework is the only entity that can create BundleContext objects and they are only valid
within the Framework that created them.
A Bundle can be adapted to its BundleContext. In order for this to succeed, the caller must have the
appropriate AdminPermission[bundle,CONTEXT] if the Java Runtime Environment supports per-
missions.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
□ Adds the specified BundleListener object to the context bundle's list of listeners if not already
present. BundleListener objects are notified when a bundle has a lifecycle state change.
If the context bundle's list of listeners already contains a listener l such that (l==listener), this
method does nothing.
Throws IllegalStateException– If this BundleContext is no longer valid.
SecurityException– If listener is a SynchronousBundleListener and the caller does not have the ap-
propriate AdminPermission[context bundle,LISTENER], and the Java Runtime Environment sup-
ports permissions.
See Also BundleEvent, BundleListener
• If the specified class name, clazz, is not null, the service must have been registered with the speci-
fied class name. The complete list of class names with which a service was registered is available
from the service's objectClass property.
• If the specified filter is not null, the filter expression must match the service.
• If the Java Runtime Environment supports permissions, the caller must have ServicePermission
with the GET action for at least one of the class names under which the service was registered.
Returns An array of ServiceReference objects or null if no services are registered which satisfy the search.
Throws InvalidSyntaxException– If the specified filter contains an invalid filter expression that cannot be
parsed.
IllegalStateException– If this BundleContext is no longer valid.
Since 1.3
Throws SecurityException– If the caller does not have the appropriate PropertyPermission to read the prop-
erty, and the Java Runtime Environment supports permissions.
Returns A service object for the service associated with reference or null if the service is not registered, the
service object returned by a ServiceFactory does not implement the classes under which it was reg-
istered or the ServiceFactory threw an exception.
Throws SecurityException– If the caller does not have the ServicePermission to get the service using at least
one of the named classes the service was registered under and the Java Runtime Environment sup-
ports permissions.
IllegalStateException– If this BundleContext is no longer valid.
IllegalArgumentException– If the specified ServiceReference was not created by the same frame-
work instance as this BundleContext.
See Also ungetService(ServiceReference), ServiceFactory
□ Returns the ServiceObjects object for the service referenced by the specified ServiceReference ob-
ject.
The ServiceObjects object can be used to obtain multiple service objects for services with prototype
scope.
For services with singleton or bundle scope, the ServiceObjects.getService() method behaves the
same as the getService(ServiceReference) method and the ServiceObjects.ungetService(Object)
method behaves the same as the ungetService(ServiceReference) method. That is, only one, use-
counted service object is available from the ServiceObjects object.
This method will always return null when the service associated with the specified reference has
been unregistered.
Returns A ServiceObjects object for the service associated with the specified reference or null if the service is
not registered.
Throws SecurityException– If the caller does not have the ServicePermission to get the service using at least
one of the named classes the service was registered under and the Java Runtime Environment sup-
ports permissions.
IllegalStateException– If this BundleContext is no longer valid.
IllegalArgumentException– If the specified ServiceReference was not created by the same frame-
work instance as this BundleContext.
See Also PrototypeServiceFactory
Since 1.8
The returned ServiceReference object is valid at the time of the call to this method. However as the
Framework is a very dynamic environment, services can be modified or unregistered at any time.
This method is the same as calling getServiceReferences(Class, String) with a null filter expression.
It is provided as a convenience for when the caller is interested in any service that implements the
specified class.
If multiple such services exist, the service with the highest ranking (as specified in its
Constants.SERVICE_RANKING property) is returned.
If there is a tie in ranking, the service with the lowest service id (as specified in its
Constants.SERVICE_ID property); that is, the service that was registered first is returned.
Returns A ServiceReference object, or null if no services are registered which implement the specified class.
Throws IllegalStateException– If this BundleContext is no longer valid.
See Also getServiceReferences(Class, String)
Since 1.6
• If the specified class name, clazz, is not null, the service must have been registered with the speci-
fied class name. The complete list of class names with which a service was registered is available
from the service's objectClass property.
• If the specified filter is not null, the filter expression must match the service.
• If the Java Runtime Environment supports permissions, the caller must have ServicePermission
with the GET action for at least one of the class names under which the service was registered.
• For each class name with which the service was registered, calling
ServiceReference.isAssignableTo(Bundle, String) with the context bundle and the class name on
the service's ServiceReference object must return true
Returns An array of ServiceReference objects or null if no services are registered which satisfy the search.
Throws InvalidSyntaxException– If the specified filter contains an invalid filter expression that cannot be
parsed.
IllegalStateException– If this BundleContext is no longer valid.
• The service must have been registered with the name of the specified class. The complete list of
class names with which a service was registered is available from the service's objectClass prop-
erty.
• If the specified filter is not null, the filter expression must match the service.
• If the Java Runtime Environment supports permissions, the caller must have ServicePermission
with the GET action for at least one of the class names under which the service was registered.
• For each class name with which the service was registered, calling
ServiceReference.isAssignableTo(Bundle, String) with the context bundle and the class name on
the service's ServiceReference object must return true
Returns A collection of ServiceReference objects. May be empty if no services are registered which satisfy
the search.
Throws InvalidSyntaxException– If the specified filter contains an invalid filter expression that cannot be
parsed.
IllegalStateException– If this BundleContext is no longer valid.
Since 1.6
1. If a bundle containing the same location identifier is already installed, the Bundle object for that
bundle is returned.
2. The bundle's content is read from the input stream. If this fails, a BundleException is thrown.
3. The bundle's associated resources are allocated. The associated resources minimally consist of a
unique identifier and a persistent storage area if the platform has file system support. If this step
fails, a BundleException is thrown.
4. The bundle's state is set to INSTALLED.
5. A bundle event of type BundleEvent.INSTALLED is fired.
6. The Bundle object for the newly or previously installed bundle is returned.
• Bundle is not installed. If there was an existing bundle for the specified location, then that bun-
dle must still be in the state it was prior to calling this method.
properties The properties for this service. The keys in the properties object must all be String ob-
jects. See Constants for a list of standard service property keys. Changes should not
be made to this object after calling this method. To update the service's properties the
ServiceRegistration.setProperties(Dictionary) method must be called. The set of properties may be
null if the service has no properties.
□ Registers the specified service object with the specified properties under the specified class names
into the Framework. A ServiceRegistration object is returned. The ServiceRegistration object is
for the private use of the bundle registering the service and should not be shared with other bun-
dles. The registering bundle is defined to be the context bundle. Other bundles can locate the ser-
vice by using one of the getServiceReferences(Class, String), getServiceReferences(String, String),
getServiceReference(Class) or getServiceReference(String) methods.
A bundle can register a service object that implements the ServiceFactory interface to have more
flexibility in providing service objects to other bundles.
The following steps are required to register a service:
Returns A ServiceRegistration object for use by the bundle registering the service to update the service's
properties or to unregister the service.
Throws IllegalArgumentException– If one of the following is true:
• service is null.
• service does not implement ServiceFactory and is not an instance of all the specified classes.
• properties contains case variants of the same key name.
SecurityException– If the caller does not have the ServicePermission to register the service for all
the named classes and the Java Runtime Environment supports permissions.
IllegalStateException– If this BundleContext is no longer valid.
See Also ServiceRegistration, PrototypeServiceFactory, ServiceFactory
10.1.7.22 public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties)
clazz The class name under which the service can be located.
service The service object or an object implementing ServiceFactory.
properties The properties for this service.
□ Registers the specified service object with the specified properties under the specified class name
with the Framework.
This method is otherwise identical to registerService(String[], Object, Dictionary) and is provided as
a convenience when service will only be registered under a single class name. Note that even in this
case the value of the service's Constants.OBJECTCLASS property will be an array of string, rather
than just a single string.
Returns A ServiceRegistration object for use by the bundle registering the service to update the service's
properties or to unregister the service.
Throws IllegalStateException– If this BundleContext is no longer valid.
See Also registerService(String[], Object, Dictionary)
If listener is not contained in the context bundle's list of listeners, this method does nothing.
Throws IllegalStateException– If this BundleContext is no longer valid.
SecurityException– If listener is a SynchronousBundleListener and the caller does not have the ap-
propriate AdminPermission[context bundle,LISTENER], and the Java Runtime Environment sup-
ports permissions.
1. If the context bundle's use count for the service is zero or the service has been unregistered, false
is returned.
2. The context bundle's use count for the service is decremented by one.
3. If the context bundle's use count for the service is now zero and the service has bundle or pro-
totype scope, the ServiceFactory.ungetService(Bundle, ServiceRegistration, Object) method is
called to release the service object for the context bundle.
4. true is returned.
Returns false if the context bundle's use count for the service is zero or if the service has been unregistered;
true otherwise.
Throws IllegalStateException– If this BundleContext is no longer valid.
IllegalArgumentException– If the specified ServiceReference was not created by the same frame-
work instance as this BundleContext.
See Also getService(ServiceReference), ServiceFactory
The bundle's BundleActivator stop method is about to be called if the bundle has a bundle activator
class. This event is only delivered to SynchronousBundleListener s. It is not delivered to BundleLis-
teners.
See Also Bundle.stop()
Since 1.3
• INSTALLED
• RESOLVED
• LAZY_ACTIVATION
• STARTING
• STARTED
• STOPPING
• STOPPED
• UPDATED
• UNRESOLVED
• UNINSTALLED
Since 1.6
Since 1.5
Examples:
org.osgi.example.bundle
org.osgi.example.*
*
BundlePermission has four actions: provide, require, host, and fragment. The provide action implies
the require action.
Since 1.3
Concurrency Thread-safe
Returns true if obj is a BundlePermission, and has the same bundle symbolic name and actions as this
BundlePermission object; false otherwise.
Returns true if the specified BundlePermission action is implied by this object; false otherwise.
• The provide action allows a bundle to provide a capability matching the specified filter.
• The require action allows a bundle to require a capability matching the specified filter.
Since 1.6
Concurrency Thread-safe
Examples:
com.acme.capability.*
org.foo.capability
*
For the require action, the name can also be a filter expression. The filter gives access to the capabili-
ty attributes as well as the following attributes:
• signer - A Distinguished Name chain used to sign the bundle providing the capability. Wildcards
in a DN are not matched according to the filter string rules, but according to the rules defined for
a DN chain.
• location - The location of the bundle providing the capability.
• id - The bundle ID of the bundle providing the capability.
• name - The symbolic name of the bundle providing the capability.
• capability.namespace - The namespace of the required capability.
Since the above attribute names may conflict with attribute names of a capability, you can prefix an
attribute name with '@' in the filter expression to match against the capability attributes and not
one of the above attributes. Filter attribute names are processed in a case sensitive manner.
There are two possible actions: require and provide. The require permission allows the owner of this
permission to require a capability matching the attributes. The provide permission allows the bun-
dle to provide a capability in the specified capability namespace.
Throws IllegalArgumentException– If the specified name is a filter expression and either the specified ac-
tion is not require or the filter has an invalid syntax.
10.1.13.4 public CapabilityPermission(String namespace, Map<String, ?> attributes, Bundle providingBundle, String
actions)
namespace The requested capability namespace.
attributes The requested capability attributes.
If the Java Runtime Environment supports permissions, it is recommended that the caller is checked
for some appropriate permission before returning the configuration object.
Returns The configuration object for this service.
Throws SecurityException– If the caller does not have an appropriate permission and the Java Runtime En-
vironment supports permissions.
Deprecated As of 1.2. Please use Configuration Admin service.
Bundle-ActivationPolicy: lazy
The header value may be retrieved from the Dictionary object returned by the Bundle.getHeaders
method.
See Also BUNDLE_LOCALIZATION_DEFAULT_BASENAME
Since 1.3
Import-Package: org.osgi.framework;
bundle-symbolic-name="com.acme.module.test"
The bundle-version attribute value uses a mathematical interval notation to specify a range of bun-
dle versions. A bundle-version attribute value specified as a single version means a version range
that includes any bundle version greater than or equal to the specified version.
See Also REQUIRE_BUNDLE
Since 1.3
This directive is also used by the Bundle-ActivationPolicy manifest header to identify the packages
from which class loads will not trigger lazy activation. The directive value is encoded in the Bun-
dle-ActivationPolicy manifest header like:
Bundle-SymbolicName: com.acme.module.test;
fragment-attachment:="resolve-time"
The ${abspath} is used by the framework to substitute the actual absolute file path.
Since 1.5
If this property is not set, the framework should use a reasonable platform default for the persistent
storage area.
Since 1.5
The value of this property may be retrieved by calling the BundleContext.getProperty method.
See Also FRAMEWORK_SYSTEMPACKAGES
Since 1.5
This directive is also used by the Bundle-ActivationPolicy manifest header to identify the packages
from which class loads will trigger lazy activation. The directive value is encoded in the Bundle-Ac-
tivationPolicy manifest header like:
• A bundle can use this service property to notify the distribution provider that these intents are
already implemented by the exported service object.
• A distribution provider must use this property to convey the combined intents of: the exporting
service, the intents that the exporting distribution provider adds, and the intents that the import-
ing distribution provider adds.
To export a service, a distribution provider must expand any qualified intents. Both the exporting
and importing distribution providers must recognize all intents before a service can be distributed.
The value of this property must be of type String, String[], or Collection of String.
See Also Remote Services Specification
Since 1.6
Since 1.3
"(cn=Babs Jensen)"
"(!(cn=Tim Howes))"
"(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Jensen)(cn=Babs J*)))"
"(o=univ*of*mich*)"
See Also Core Specification, Filters, for a description of the filter string syntax.
Since 1.1
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
Since 1.9
• STARTED
• ERROR
• WARNING
• INFO
• PACKAGES_REFRESHED
• STARTLEVEL_CHANGED
• STOPPED
• STOPPED_BOOTCLASSPATH_MODIFIED
• STOPPED_UPDATE
• WAIT_TIMEDOUT
The most simple case is a single wildcard; it must match any DN. A wildcard can also replace the
first list of RDNs of a DN. The first RDNs are the least significant. Such lists of matched RDNs can be
empty.
For example, a match pattern with a wildcard that matches all DNs that end with RDNs of o=ACME
and c=US would look like this:
*, o=ACME, c=US
If a wildcard is used for a value of an RDN, the value must be exactly *. The wildcard must match
any value, and no substring matching must be done. For example:
cn=*,o=ACME,c=*
This match pattern with wildcard must match the following DNs:
cn=Bugs Bunny,o=ACME,c=US
cn = Daffy Duck , o = ACME , c = US
cn=Road Runner, o=ACME, c=NL
But not:
o=ACME, c=NL
dc=acme.com, cn=Bugs Bunny, o=ACME, c=US
A match pattern may contain a chain of DN match patterns. The semicolon( ';' \u003B) must be used
to separate DN match patterns in a chain. Wildcards can also be used to match against a complete
DN within a chain.
The following example matches a certificate signed by Tweety Inc. in the US.
The wildcard ('*') matches zero or one DN in the chain, however, sometimes it is necessary to match
a longer chain. The minus sign ( '-' \u002D) represents zero or more DNs, whereas the asterisk only
represents a single DN. For example, to match a DN where the Tweety Inc. is in the DN chain, use
the following expression:
Returns true If the pattern matches the DN chain; otherwise false is returned.
Throws IllegalArgumentException– If the specified match pattern or DN chain is invalid.
Since 1.5
This method creates an InvalidSyntaxException object with the specified message and the filter
string which generated the exception.
Since 1.3
org.osgi.service.http
PackagePermission has three actions: exportonly, import and export. The export action, which is
deprecated, implies the import action.
Concurrency Thread-safe
Examples:
org.osgi.service.http
javax.servlet.*
*
For the import action, the name can also be a filter expression. The filter gives access to the follow-
ing attributes:
• signer - A Distinguished Name chain used to sign the exporting bundle. Wildcards in a DN are
not matched according to the filter string rules, but according to the rules defined for a DN chain.
• location - The location of the exporting bundle.
• id - The bundle ID of the exporting bundle.
• name - The symbolic name of the exporting bundle.
• package.name - The name of the requested package.
Returns true if the specified permission is implied by this object; false otherwise.
Concurrency Immutable
• UNREGISTERING
and null is returned to the bundle. If this method is recursively called for the specified bundle, a
framework event of type FrameworkEvent.ERROR is fired containing a service exception of type
ServiceException.FACTORY_RECURSION and null is returned to the bundle.
The Framework caches the valid service object and will return the same service object on any future
call to BundleContext.getService(ServiceReference) for the specified bundle. This means the Frame-
work must not allow this method to be concurrently called for the specified bundle.
Returns A service object that must be an instance of all the classes named when the service was registered.
See Also BundleContext.getService(ServiceReference)
Returns A service object for the associated service or null if the service is not registered, the customized ser-
vice object returned by a ServiceFactory does not implement the classes under which it was regis-
tered or the ServiceFactory threw an exception.
Throws IllegalStateException– If the BundleContext used to create this ServiceObjects object is no longer
valid.
See Also ungetService(Object)
1. If the associated service has been unregistered, this method returns without doing anything.
2. The use count for the specified service object is decremented by one.
3. If the use count for the specified service object is now zero, the
PrototypeServiceFactory.ungetService(Bundle, ServiceRegistration, Object) method is called to
release the specified service object.
The specified service object must no longer be used and all references to it should be destroyed after
calling this method when the use count has returned to zero.
Throws IllegalStateException– If the BundleContext used to create this ServiceObjects object is no longer
valid.
IllegalArgumentException– If the specified service object is null or was not provided by a Ser-
viceObjects object for the associated service.
See Also getService()
• The register action allows a bundle to register a service on the specified names.
• The get action allows a bundle to detect a service and get it.
Permission to get a service is required in order to detect events regarding the service. Untrusted bun-
dles should not be able to detect the presence of certain services unless they have the appropriate
ServicePermission to get the specific service.
Concurrency Thread-safe
Examples:
org.osgi.service.http.HttpService
org.osgi.service.http.*
*
For the get action, the name can also be a filter expression. The filter gives access to the service prop-
erties as well as the following attributes:
• signer - A Distinguished Name chain used to sign the bundle publishing the service. Wildcards
in a DN are not matched according to the filter string rules, but according to the rules defined for
a DN chain.
• location - The location of the bundle publishing the service.
• id - The bundle ID of the bundle publishing the service.
• name - The symbolic name of the bundle publishing the service.
Since the above attribute names may conflict with service property names used by a service, you
can prefix an attribute name with '@' in the filter expression to match against the service property
and not one of the above attributes. Filter attribute names are processed in a case sensitive manner
unless the attribute references a service property. Service properties names are case insensitive.
There are two possible actions: get and register. The get permission allows the owner of this permis-
sion to obtain a service with this name. The register permission allows the bundle to register a ser-
vice under that name.
Throws IllegalArgumentException– If the specified name is a filter expression and either the specified ac-
tion is not get or the filter has an invalid syntax.
Returns A copy of the properties of the service referenced by this ServiceReference object
Since 1.9
Returns true if the bundle which registered the service referenced by this ServiceReference and the specified
bundle use the same source for the package of the specified class name. Otherwise false is returned.
Throws IllegalArgumentException– If the specified Bundle was not created by the same framework instance
as this ServiceReference .
Since 1.3
1. The service is removed from the Framework service registry so that it can no longer be obtained.
2. A service event of type ServiceEvent.UNREGISTERING is fired so that bundles using this ser-
vice can release their use of the service. Once delivery of the service event is complete, the Ser-
viceReference objects for the service may no longer be used to get a service object for the service.
3. For each bundle whose use count for this service is greater than zero:
• The bundle's use count for this service is set to zero.
• If the service was registered with a ServiceFactory object, the ServiceFactory.ungetService
method is called to release the service object for the bundle.
are called with a BundleEvent object when a bundle has been installed, resolved, starting, started,
stopping, stopped, updated, unresolved, or uninstalled.
Unlike normal BundleListener objects, SynchronousBundleListeners are synchronously called dur-
ing bundle lifecycle processing. The bundle lifecycle processing will not proceed until all Synchro-
nousBundleListeners have completed. SynchronousBundleListener objects will be called prior to
BundleListener objects.
AdminPermission[bundle,LISTENER] is required to add or remove a SynchronousBundleListener ob-
ject.
See Also BundleEvent
Since 1.1
Concurrency Thread-safe
4. Qualifier. A text string. See Version(String) for the format of the qualifier string.
10.1.33.3 public Version(int major, int minor, int micro, String qualifier)
major Major component of the version identifier.
minor Minor component of the version identifier.
micro Micro component of the version identifier.
qualifier Qualifier component of the version identifier. If null is specified, then the qualifier will be set to the
empty string.
□ Creates a version identifier from the specified components.
Throws IllegalArgumentException– If the numerical components are negative or the qualifier string is in-
valid.
micro component is less than the other version's micro component, or the major, minor and micro
components are equal and it's qualifier component is less than the other version's qualifier compo-
nent (using String.compareTo).
A version is considered to be equal to another version if the major, minor and micro components
are equal and the qualifier component is equal (using String.compareTo).
Returns A negative integer, zero, or a positive integer if this version is less than, equal to, or greater than the
specified Version object.
Throws ClassCastException– If the specified object is not a Version object.
The format of the version string will be major.minor.micro if qualifier is the empty string or
major.minor.micro.qualifier otherwise.
Returns The string representation of this version identifier.
10.1.34.5 public VersionRange(char leftType, Version leftEndpoint, Version rightEndpoint, char rightType)
leftType Must be either LEFT_CLOSED or LEFT_OPEN .
leftEndpoint Left endpoint of range. Must not be null.
rightEndpoint Right endpoint of range. May be null to indicate the right endpoint is Infinity.
rightType Must be either RIGHT_CLOSED or RIGHT_OPEN.
10.2 org.osgi.framework.launch
Framework Launch Package Version 1.2.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
10.2.1 Summary
• Framework - A Framework instance.
• FrameworkFactory - A factory for creating Framework instances.
Returns null as a framework implementation does not have a proper bundle from which to return an entry.
The method returns immediately to the caller after initiating the following steps to be taken on an-
other thread.
Throws BundleException– If stopping and restarting this Framework could not be initiated.
SecurityException– If the caller does not have the appropriate AdminPermission[this,LIFECYCLE],
and the Java Runtime Environment supports permissions.
/META-INF/services/org.osgi.framework.launch.FrameworkFactory
This UTF-8 encoded resource must contain the name of the framework implementation's Frame-
workFactory implementation class. Space and tab characters, including blank lines, in the resource
must be ignored. The number sign ('#' \u0023) and all characters following it on each line are a com-
ment and must be ignored.
Launchers can find the name of the FrameworkFactory implementation class in the resource and
then load and construct a FrameworkFactory object for the framework implementation. The Frame-
workFactory implementation class must have a public, no-argument constructor. Java™ SE 6 intro-
duced the ServiceLoader class which can create a FrameworkFactory instance from the resource.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
10.3 org.osgi.resource
Resource Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest. For example:
10.3.1 Summary
• Capability - A capability that has been declared from a Resource.
• Namespace - Capability and Requirement Namespaces base class.
• Requirement - A requirement that has been declared from a Resource .
• Resource - A resource is the representation of a uniquely identified and typed data.
• Wire - A wire connecting a Capability to a Requirement.
• Wiring - A wiring for a resource.
Instances of this type must be effectively immutable. That is, for a given instance of this interface, the
methods defined by this interface must always return the same result.
Concurrency Thread-safe
fragment resources of this wiring. There is no ordering defined between requirements in different
namespaces.
10.4 org.osgi.framework.wiring
Framework Wiring Package Version 1.2.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest. For example:
10.4.1 Summary
• BundleCapability - A capability that has been declared from a bundle revision.
• BundleRequirement - A requirement that has been declared from a bundle revision.
• BundleRevision - Bundle Revision.
• BundleRevisions - The bundle revisions of a bundle.
• BundleWire - A wire connecting a BundleCapability to a BundleRequirement.
• BundleWiring - A wiring for a bundle.
• FrameworkWiring - Query and modify wiring information for the framework.
For a bundle that has not been uninstalled, the most recent bundle revision is defined to be the cur-
rent bundle revision. A bundle in the UNINSTALLED state does not have a current revision. The cur-
rent bundle revision for a bundle can be obtained by calling bundle.adapt (BundleRevision.class).
Since a bundle in the UNINSTALLED state does not have a current revision, adapting such a bundle
returns null.
The framework defines namespaces for package, bundle and host capabilities and requirements.
These namespaces are defined only to express wiring information by the framework. They must not
be used in Provide-Capability and Require-Capability manifest headers.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
tribute must contain the Version of the package if one is specified or Version.emptyVersion if not
specified. The bundle-symbolic-name capability attribute must contain the symbolic name of the
provider if one is specified. The bundle-version capability attribute must contain the version of the
provider if one is specified or Version.emptyVersion if not specified.
The package capabilities provided by the system bundle, that is the bundle with id zero, must
include the package specified by the Constants.FRAMEWORK_SYSTEMPACKAGES and
Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA framework properties as well as any other
package exported by the framework implementation.
A bundle revision declares zero or more package capabilities (this is, exported packages) and de-
clares zero or more package requirements.
A bundle wiring provides zero or more resolved package capabilities (that is, exported packages)
and requires zero or more resolved package requirements (that is, imported packages). The number
of package wires required by a bundle wiring may change as the bundle wiring may dynamically
import additional packages.
See Also PackageNamespace
• TYPE_FRAGMENT
A bundle revision may be more than one type at a time. A type code is used to identify the bundle re-
vision type for future extendability.
If this bundle revision is not one or more of the defined types then 0 is returned.
Returns The special types of this bundle revision. The type values are ORed together.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
This bit may be set when calling listResources(String, String, int) to specify the result must include
the names of matching resources from the specified path and its subdirectories. If this bit is not set,
then the result must only include names of matching resources from the specified path.
See Also listResources(String, String, int)
† The identity capability provided by attached fragment revisions must not be included in the capa-
bilities of the host bundle wiring.
Returns A list containing a snapshot of the BundleCapabilitys, or an empty list if this bundle wiring provides
no capabilities in the specified namespace. If this bundle wiring is not in use, null will be returned.
For a given namespace, the list contains the capabilities in the order the capabilities were specified
in the manifests of the bundle revision and the attached fragments† of this bundle wiring. There is
no ordering defined between capabilities in different namespaces.
Since 1.1
some may be discarded. For example, if a package is declared to be both exported and imported, only
one is selected and the other is discarded.
A wiring for a fragment resource with a symbolic name must provide exactly one osgi.identity capa-
bility.
† The osgi.identity capability provided by attached fragment resource must not be included in the
capabilities of the host wiring.
This method returns the same value as getCapabilities(String).
Returns A list containing a snapshot of the Capabilitys, or an empty list if this wiring provides no capabili-
ties in the specified namespace. For a given namespace, the list contains the capabilities in the order
the capabilities were specified in the manifests of the resource and the attached fragment resources†
of this wiring. There is no ordering defined between capabilities in different namespaces.
Since 1.1
• Only the resource names for resources in bundle wirings will be returned. The names of re-
sources visible to a bundle wiring's parent class loader, such as the bootstrap class loader, must
not be included in the result.
• Only established wires will be examined for resources. This method must not cause new wires
for dynamic imports to be established.
Returns An unmodifiable collection of resource names for each matching resource, or an empty collection if
no matching resource could be found, if this bundle wiring is for a fragment revision or if the caller
does not have the appropriate AdminPermission[bundle,RESOURCE] and the Java Runtime Envi-
ronment supports permissions. The collection is unordered and must contain no duplicate resource
names. If this bundle wiring is not in use, null must be returned.
Each returned capability must match the given requirement. This means that the filter in the re-
quirement must match as well as any namespace specific directives. For example, the mandatory at-
tributes for the osgi.wiring.package namespace.
The returned collection has not been filtered to remove capabilities that are non-effective, substi-
tuted or for which the providing bundle does not have permission to provide. No resolve hooks are
called to filter matching capabilities.
Returns A collection of BundleCapability objects that match the specified requirement.
Since 1.2
1. Compute the dependency closure of the specified bundles. If no bundles are specified, compute
the dependency closure of the removal pending bundles.
2. Each bundle in the dependency closure that is in the ACTIVE state will be stopped as described in
the Bundle.stop method.
3. Each bundle in the dependency closure that is in the RESOLVED state is unresolved and thus
moved to the INSTALLED state. The effect of this step is that bundles in the dependency closure
are no longer RESOLVED.
4. Each bundle in the dependency closure that is in the UNINSTALLED state is removed from the
dependency closure and is now completely removed from the Framework.
5. Each bundle in the dependency closure that was in the ACTIVE state prior to Step 2 is started as
described in the Bundle.start method, causing all bundles required for the restart to be resolved.
It is possible that, as a result of the previous steps, packages that were previously exported no
longer are. Therefore, some bundles may be unresolvable until bundles satisfying the dependen-
cies have been installed in the Framework.
For any exceptions that are thrown during any of these steps, a framework event of type
FrameworkEvent.ERROR is fired containing the exception. The source bundle for these events
should be the specific bundle to which the exception is related. If no specific bundle can be associat-
ed with the exception then the System Bundle must be used as the source bundle for the event. All
framework events fired by this method are also delivered to the specified FrameworkListeners in the
order they are specified.
When this process completes after the bundles are refreshed, the Framework will fire a
Framework event of type FrameworkEvent.PACKAGES_REFRESHED to announce it has com-
pleted the bundle refresh. The specified FrameworkListeners are notified in the order spec-
ified. Each specified FrameworkListener will be called with a Framework event of type
FrameworkEvent.PACKAGES_REFRESHED.
Throws IllegalArgumentException– If the specified Bundles were not created by the same framework in-
stance associated with this FrameworkWiring.
SecurityException– If the caller does not have AdminPermission[System Bundle,RESOLVE] and the
Java runtime environment supports permissions.
10.5 org.osgi.framework.startlevel
Framework Start Level Package Version 1.0.
The Framework Start Level package allows management agents to manage a start level assigned to
each bundle and the active start level of the Framework. This package is a replacement for the now
deprecated org.osgi.service.startlevel package.
A start level is defined to be a state of execution in which the Framework exists. Start level values
are defined as unsigned integers with 0 (zero) being the state where the Framework is not launched.
Progressively higher integral values represent progressively higher start levels. For example, 2 is a
higher start level than 1.
AdminPermission is required to modify start level information.
Start Level support in the Framework includes the ability to modify the active start level of the
Framework and to assign a specific start level to a bundle. The beginning start level of a Framework
is specified via the org.osgi.framework.Constants.FRAMEWORK_BEGINNING_STARTLEVEL frame-
work property when configuring a framework.
When the Framework is first started it must be at start level zero. In this state, no bundles are
running. This is the initial state of the Framework before it is launched. When the Framework is
launched, the Framework will enter start level one and all bundles which are assigned to start lev-
el one and whose autostart setting indicates the bundle should be started are started as described in
the org.osgi.framework.Bundle.start(int) method. The Framework will continue to increase the start
level, starting bundles at each start level, until the Framework has reached a beginning start level. At
this point the Framework has completed starting bundles and will then fire a Framework event of
type org.osgi.framework.FrameworkEvent.STARTED to announce it has completed its launch.
Within a start level, bundles may be started in an order defined by the Framework implementation.
This may be something like ascending org.osgi.framework.Bundle.getBundleId() order or an order
based upon dependencies between bundles. A similar but reversed order may be used when stop-
ping bundles within a start level.
The Framework Start Level package can be used by management bundles to alter the active start lev-
el of the framework.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest. For example:
10.5.1 Summary
• BundleStartLevel - Query and modify the start level information for a bundle.
• FrameworkStartLevel - Query and modify the start level information for the framework.
The autostart setting of a bundle indicates whether the bundle's declared activation policy is to be
used when the bundle is started.
Returns true if the bundle's autostart setting indicates the activation policy declared in the manifest must be
used. false if the bundle must be eagerly activated.
Throws IllegalStateException– If the bundle has been uninstalled.
See Also Bundle.START_ACTIVATION_POLICY
1. Change the active start level to the intermediate start level value.
2. Start bundles at the intermediate start level whose autostart setting indicate they must
be started. They are started as described in the Bundle.start(int) method using the
Bundle.START_TRANSIENT option. The Bundle.START_ACTIVATION_POLICY option must al-
so be used if BundleStartLevel.isActivationPolicyUsed() returns true for the bundle.
When this process completes after the specified start level is reached, the Framework will fire a
Framework event of type FrameworkEvent.STARTLEVEL_CHANGED to announce it has moved to the
specified start level.
If the specified start level is lower than the active start level, the Framework will continue to de-
crease the start level until the Framework has reached the specified start level. At each intermediate
start level value on the way to and including the specified start level, the framework must:
1. Stop bundles at the intermediate start level as described in the Bundle.stop(int) method using
the Bundle.STOP_TRANSIENT option.
2. Change the active start level to the intermediate start level value.
When this process completes after the specified start level is reached, the Framework will fire a
Framework event of type FrameworkEvent.STARTLEVEL_CHANGED to announce it has moved to the
specified start level.
If the specified start level is equal to the active start level, then no bundles are
started or stopped, however, the Framework must fire a Framework event of type
FrameworkEvent.STARTLEVEL_CHANGED to announce it has finished moving to the specified start
level. This event may arrive before this method returns.
Throws IllegalArgumentException– If the specified start level is less than or equal to zero.
SecurityException– If the caller does not have AdminPermission[System Bundle,STARTLEVEL] and
the Java runtime environment supports permissions.
10.6 org.osgi.framework.namespace
Namespace Package Version 1.1.
Bundles should not need to import this package at runtime since all the types in this package just
contain constants for capability and requirement namespaces specified by the OSGi Alliance.
10.6.1 Summary
• AbstractWiringNamespace - Wiring Capability and Requirement Namespaces base class.
• BundleNamespace - Bundle Capability and Requirement Namespace.
• ExecutionEnvironmentNamespace - Execution Environment Capability and Requirement
Namespace.
• HostNamespace - Host Capability and Requirement Namespace.
• IdentityNamespace - Identity Capability and Requirement Namespace.
• NativeNamespace - Native Capability and Requirement Namespace.
• PackageNamespace - Package Capability and Requirement Namespace.
• The uses directive must be ignored. A uses directive specified on the Bundle-SymbolicName
header must be ignored. A uses directive must not be present in the capability.
• The effective directives must be ignored. This namespace is only effective at resolve time. An ef-
fective directive specified on the Bundle-SymbolicName or Require-Bundle headers must be ig-
nored. An effective directive must not be present in a capability or requirement.
• The cardinality directive must be ignored. A cardinality directive specified on the Require-Bun-
dle header must be ignored. A cardinality directive must not be present in a requirement.
A non-fragment resource with the osgi.bundle type identity provides exactly one† bundle capability
(that is, the bundle can be required by another bundle). A fragment resource with the osgi.fragment
type identity must not declare a bundle capability. A resource requires zero or more bundle require-
ments (that is, required bundles).
† A resource with no symbolic name must not provide a bundle capability.
Concurrency Immutable
• The uses directive must be ignored. A uses directive specified on the Bundle-SymbolicName
header must be ignored. A uses directive must not be present in the capability.
• The effective directives must be ignored. This namespace is only effective at resolve time. An ef-
fective directive specified on the Bundle-SymbolicName or Fragment-Host headers must be ig-
nored. An effective directive must not be present in a capability or requirement.
• The cardinality directive has limited applicability to this namespace. A cardinality directive spec-
ified on the Fragment-Host header must be ignored. All requirements must have the cardinality
directive set to multiple.
A non-fragment resource with the with the osgi.bundle type identity provides zero or one† host ca-
pabilities. A fragment resource with the osgi.fragment type identity must not declare a host capabil-
ity and must declare exactly one host requirement.
† A resource with no bundle symbolic name must not provide a host capability.
Concurrency Immutable
• The effective directives must be ignored. This namespace is only effective at resolve time. An ef-
fective directive specified on the Export-Package, Import-Package or DynamicImport-Package
headers must be ignored. An effective directive must not be present in a capability or require-
ment.
• The cardinality directive has limited applicability to this namespace. A cardinality directive spec-
ified on the Import-Package or DynamicImport-Package headers must be ignored. Only require-
ments with resolution set to dynamic and the package name contains a wildcard must have the
cardinality directive set to multiple. Otherwise, a cardinality directive must not be present in a re-
quirement.
Concurrency Immutable
10.7 org.osgi.annotation.versioning
OSGi Versioning Annotations Package Version 1.1.
This package is not used at runtime.
See Also Semantic Versioning [https://www.osgi.org/wp-content/uploads/SemanticVersioning1.pdf]
10.7.1 Summary
• ConsumerType - A type implemented by, or extended by, the Consumer Role.
• ProviderType - A type implemented by, or extended by, the Provider Role.
• Version - Specify the version of a package.
10.7.2 @ConsumerType
A type implemented by, or extended by, the Consumer Role.
A non-binary-compatible change to a consumer type or a binary-compatible change to a consumer
type affecting an abstract method normally requires incrementing the major version of the type's
package. This change will require all providers and all consumers to be updated to handle the
change since consumers that implement or extend the consumer type and all providers must under-
stand the change in the consumer type.
A binary-compatible change to a consumer type not affecting an abstract method normally requires
incrementing the minor version of the type's package. This change will require all providers to be
updated to handle the change, but consumers will not require changes since no abstract methods re-
quiring implementation by the consumer are affected.
A type can be marked ConsumerType or ProviderType but not both. A type is assumed to be Con-
sumerType if it is not marked either ConsumerType or ProviderType.
A package can be marked ProviderType. In this case, all types in the package are considered to be a
provider type regardless of whether they are marked ConsumerType or ProviderType.
This annotation is not retained at runtime. It is for use by tools to understand the semantic version
of a package. When a bundle implements a consumer type from an imported package, then the
bundle's import range for that package must require the exact major version and a minor version
greater than or equal to the package's version.
See Also Semantic Versioning [https://www.osgi.org/wp-content/uploads/SemanticVersioning1.pdf]
Retention CLASS
Target TYPE
10.7.3 @ProviderType
A type implemented by, or extended by, the Provider Role.
A non-binary-compatible change to a provider type normally requires incrementing the major ver-
sion of the type's package. This change will require all providers and all consumers to be updated
to handle the change. However, a non-binary-compatible change affecting a protected access mem-
ber only requires incrementing the minor version of the type's package. This change will require all
providers to be updated to handle the change, but consumers will not require changes since they on-
ly use, and do not extend, the provider type and thus could not access protected access members of
the provider type.
A binary-compatible change to a provider type normally requires incrementing the minor version
of the type's package. This change will require all providers to be updated to handle the change,
but consumers will not require changes since they only use, and do not implement or extend, the
provider type.
A type can be marked ConsumerType or ProviderType but not both. A type is assumed to be Con-
sumerType if it is not marked either ConsumerType or ProviderType.
A package can be marked ProviderType. In this case, all types in the package are considered to be a
provider type regardless of whether they are marked ConsumerType or ProviderType.
This annotation is not retained at runtime. It is for use by tools to understand the semantic ver-
sion of a package. When a bundle implements a provider type from an imported package, then the
bundle's import range for that package must require the package's exact major and minor version.
See Also Semantic Versioning [https://www.osgi.org/wp-content/uploads/SemanticVersioning1.pdf]
Retention CLASS
Target TYPE, PACKAGE
10.7.4 @Version
Specify the version of a package.
This annotation is not retained at runtime. It is for use by tools to generate bundle manifests or oth-
erwise process the version of a package.
See Also Semantic Versioning [https://www.osgi.org/wp-content/uploads/SemanticVersioning1.pdf]
Retention CLASS
Target PACKAGE
10.8 org.osgi.annotation.bundle
OSGi Bundle Annotations Package Version 1.0.
10.8.1 Summary
• Attribute - Mark an annotation element as an attribute.
• Capabilities - Container annotation for repeated Capability annotations.
• Capability - Define a capability for a bundle.
• Directive - Mark an annotation element as a directive.
• Export - Mark a package to be exported from its bundle.
• Export.Substitution - Substitution policy for this package.
• Header - Define a manifest header for a bundle.
• Headers - Container annotation for repeated Header annotations.
• Requirement - Define a requirement for a bundle.
• Requirement.Cardinality - Cardinality for this requirement.
• Requirement.Resolution - Resolution for this requirement.
• Requirements - Container annotation for repeated Requirement annotations.
10.8.2 @Attribute
Mark an annotation element as an attribute.
This is used when applying Capability or Requirement as a meta annotation to an annotation dec-
laration. The value of the annotation element annotated with Attribute is used as the value of an at-
tribute in the generated capability or requirement clause. For example:
@Capability(namespace = "my.namespace")
public @interface MyCapability {
@Attribute("attr")
String value() default "";
}
@MyCapability("foo")
public MyClass {}
The use of the MyCapability annotation, which is meta annotated with the Capability and Attribute
annotations, will result in a capability in the namespace my.namespace with the attribute attr=foo.
If the element annotated with Attribute is unspecified when applied, then the attribute must not be
generated in the generated capability or requirement clause. For example:
@MyCapability
public MyClass {}
10.8.3 @Capabilities
Container annotation for repeated Capability annotations.
Retention CLASS
Target TYPE, PACKAGE
10.8.4 @Capability
Define a capability for a bundle.
For example:
@Capability(namespace=ExtenderNamespace.EXTENDER_NAMESPACE,
name="osgi.component", version="1.3.0")
This annotation is not retained at runtime. It is for use by tools to generate bundle manifests or oth-
erwise process the type or package.
This annotation can be used to annotate an annotation. If the meta-annotated annotation declares
an element of the same name as an element in this annotation, the element is considered to override
the element in this annotation.
Retention CLASS
Target TYPE, PACKAGE
10.8.5 @Directive
Mark an annotation element as a directive.
This is used when applying Capability or Requirement as a meta annotation to an annotation decla-
ration. The value of the annotation element annotated with Directive is used as the value of a direc-
tive in the generated capability or requirement clause. For example:
@Capability(namespace = "my.namespace")
public @interface MyCapability {
@Directive("resource")
String value() default "";
}
@MyCapability("foo")
public MyClass {}
The use of the MyCapability annotation, which is meta annotated with the Capability and Direc-
tive annotations, will result in a capability in the namespace my.namespace with the directive
resource:=foo.
If the element annotated with Directive is unspecified when applied, then the directive must not be
generated in the generated capability or requirement clause. For example:
@MyCapability
public MyClass {}
10.8.6 @Export
Mark a package to be exported from its bundle.
The package must also be annotation with the Version annotation to specify the export version of
the package.
This annotation is not retained at runtime. It is for use by tools to generate bundle manifests or oth-
erwise process the package.
Retention CLASS
Target PACKAGE
10.8.7.1 CONSUMER
Use a consumer type version range for the import package clause when substitutably importing a
package.
See Also ConsumerType
10.8.7.2 PROVIDER
Use a provider type version range for the import package clause when substitutably importing a
package.
See Also ProviderType
10.8.7.3 NOIMPORT
The package must not be substitutably imported.
10.8.7.4 CALCULATED
The policy value is calculated by inspection of the classes in the package.
10.8.8 @Header
Define a manifest header for a bundle.
For example:
@Header(name=Constants.BUNDLE_CATEGORY, value="osgi")
This annotation is not retained at runtime. It is for use by tools to generate bundle manifests.
Retention CLASS
Target TYPE, PACKAGE
10.8.9 @Headers
Container annotation for repeated Header annotations.
Retention CLASS
Target TYPE, PACKAGE
10.8.10 @Requirement
Define a requirement for a bundle.
For example:
@Requirement(namespace=ExtenderNamespace.EXTENDER_NAMESPACE,
name="osgi.component", version="1.3.0")
This annotation is not retained at runtime. It is for use by tools to generate bundle manifests or oth-
erwise process the a package.
This annotation can be used to annotate an annotation. If the meta-annotated annotation declares
an element of the same name as an element in this annotation, the element is considered to override
the element in this annotation.
Retention CLASS
Target TYPE, PACKAGE
the floor version. For example, if the specified version is 1.3, then the version range expression is
(&(version>=1.3)(!(version>=2.0))).
The specified version must be a valid OSGi version string.
10.8.11.1 SINGLE
Indicates if the requirement can only be wired a single time.
10.8.11.2 MULTIPLE
Indicates if the requirement can be wired multiple times.
10.8.12.1 MANDATORY
A mandatory requirement forbids the bundle to resolve when the requirement is not satisfied.
10.8.12.2 OPTIONAL
An optional requirement allows a bundle to resolve even if the requirement is not satisfied.
10.8.13 @Requirements
Container annotation for repeated Requirement annotations.
Retention CLASS
Target TYPE, PACKAGE
50.1 Introduction
The OSGi security model is based on the powerful and flexible Java security architecture, specifical-
ly the permission model. This specification adds several new features to the Java model to adapt it to
the typical use cases of OSGi deployments.
Key aspects of this security management API is the use of policies. Policies contain a set of permis-
sions that are applicable when the related conditions are met. A policy can both allow (the Java
model) as well as deny access when the permissions are implied. Deny permissions can significant-
ly simplify security management. The real time management of Conditional Permission Admin en-
ables management applications to control the permissions of other applications with immediate ef-
fect; no restart is required.
Policies are based on the very general concept of conditions. Conditions guard access to the policy's
permissions. If they are not satisfied, then the permissions are not applicable. Conditions can be
based on the bundle signer, the bundle location, as well as on user-defined conditions. The advan-
tage of this model is that groups of permissions can be shared based on signers or locations. Con-
ditions can also be used to enable or disable a group of permissions when an external condition is
true, for example, an inserted SIM card, an online connection to the management system is estab-
lished, a specific roaming area, or a user has approved a permission after prompting. This model al-
lows an operator to create and enforce a dynamic security policies for its devices.
This specification defines a Conditional Permission Admin that supersedes the Permission Admin
(albeit its relation to Permission Admin is well-defined in this specification).
50.1.1 Essentials
• Policies - Provide a security policy system where conditions control the actual permissions that
bundles have at a certain moment in time to be allowed or denied access.
• Java Security - Provide full compatibility with the existing Java security model, existing applica-
tions must not require modifications.
• Delegation - Support a management delegation model where an Operator can delegate part of the
management of a device to another party in a secure way.
• Digital Signatures - Support the use of digital signatures in a bundle's policy decisions.
• Real Time - Changes in the environment must be reflected immediately in the bundle's permis-
sions.
• Operator Specific Conditions - It must be possible for operators, manufacturers, selected developers,
and others to provide custom conditions.
• User Confirmation - The policy model must support end user prompting and confirmations.
• Allow/Deny Policies - It must be possible to both allow access as well as specifically deny access.
• Ordering - Policies must be ordered in a table and evaluated in the given order, which is from in-
dex 0 upwards.
• Backward Compatibility - The model must be backward compatible with the Permission Admin of
earlier releases.
50.1.2 Entities
• Conditional Permission Admin - The administrative service that provides the functions to manipu-
late the policy table.
• Policy - Provides the information to allow or deny access to a resource. A policy contains a name,
an access type, a set of conditions that must all be satisfied and a set of permissions of which at
least one should be implied to specifically allow or deny access. A policy is encoded in a Condi-
tional Permission Info.
• Policy Table - A conceptual table containing all the Conditional Permission Infos.
• Conditional Permission Info - The encoded form of a Policy.
• Conditional Permission Update - Holds a temporary copy of the Policy Table so that a number of
changes can be committed as a whole.
• Permission Info - Holds a string based encoding of a Permission object.
• Condition Info - Holds a string based encoding of a Condition object.
• Condition - A Condition object is associated with a single Bundle Protection Domain. It abstracts
an external condition that can be evaluated. A condition can be mutable or immutable as well as
immediate or postponed.
• Bundle Location Condition - An immutable Condition object that is satisfied when the associated
bundle has the given location.
• Bundle Signer Condition - An immutable Condition object that is satisfied when the associated
bundle is signed by a certificate that matched the given DN.
• Permission - An object that defines a certain permission type. Same as the Java Security model.
• Bundle Protection Domain - The class that implements the Protection Domain of a bundle, this
specification does not define an interface for this class, but it plays an important role in this spec-
ification.
selects by selects by
location signer
<<class>> <<class>>
Bundle Loc. Bundle Signer
Condition Condition
*
has
1
<<interface>> <<interface>> <<interface>> <<interface>>
Conditional 1 * Cond. Perm. 1 * Cond. Perm. 1 * Permission Info
Perm. Admin has Update planned Info has
encodes
50.1.3 Synopsis
A Conditional Permission Admin service maintains a system wide ordered table of ConditionalPer-
missionInfo objects. This table is called the policy table. The policy table holds an encoded form of
conditions, permissions, and their allow/deny access type. A manager can enumerate, delete, and
add new policies to this table via a ConditionalPermissionsUpdate object.
When a bundle is created, it creates a Bundle Protection Domain. This protection domain calculates
the system permissions for that bundle by instantiating the policy table, potentially pruning any
policies that can never apply to that bundle and optimizing entries that always apply.
A bundle can have local permissions defined in a Bundle Permission Resource. These are the actual
detailed permissions needed by this bundle to operate. A bundle's effective permissions are the in-
tersection of the local permissions and the system permissions. During the permission check of the
Java Security Manager, each Protection Domain is first checked for the local permissions, if this fails,
the complete check fails.
Otherwise, the Bundle Protection Domains of the calling bundles are consulted to see if they imply
the requested permission. To imply the requested permission, the Bundle Protection Domain must
find a policy in its policy table where all conditions are satisfied and where one of the policy's per-
missions imply the requested permission. If one of the permissions is implied, then the policy's ac-
cess type decides success or failure.
Certain conditions must postpone their evaluation so that their evaluation can be minimized and
grouped to prevent unwanted side effects. Postponed conditions can leverage a Dictionary object to
maintain state during a single permission check.
developer
operator
Framework
develops audits installs
and ships
• Fine-grained - The developer has the knowledge to provide the fine-grained permissions that are
necessary to minimize the sandbox of the bundle without constraining it.
• Auditable - The Operator has a relatively small and readable file that shows the required sandbox.
It can therefore assesses the risk of running a bundle.
• Sandboxed - The Operator has the guarantee from the Framework that a bundle cannot escape its
local permissions.
developer
operator
end user
OSGi framework
local
develops audits and installs permissions
and ships signs
50.2.3 Delegation
A model where the local permissions are secured with a signature works for an Operator that fully
controls a device. The operator must sign all bundles before they are provisioned. In this case, the
Operator acts as a gatekeeper, no authority is delegated.
This can become expensive when there are third parties involved. For example, an Enterprise could
provide applications to its employees on a mobile phone that is managed by an Operator. This mod-
el is depicted in Figure 50.4. If the Enterprise always has to contact the Operator before it can provi-
sion a new version, bottlenecks quickly arise.
provides
Developer Enterprise provides signing
certificate
installs
This bottleneck problem can also be solved with signing. Signing does not only provide tamper de-
tection, it can also provide an authenticated principal. The principal can be authenticated with a cer-
tificate chain. The device contains a set of trusted certificates (depending on implementation) that
are used to authenticate the certificate of the signer.
The operator can therefore safely associate a principal with a set of permissions. These permissions
are called the system permissions. Bundles signed by that principal are then automatically granted
those system permissions.
In this model, the Operator is still fully in control. At any moment in time, the Operator can change
the system permissions associated with the principal and thereby immediately deny access to all
bundles of that principal, while they are running. Alternatively, the Operator can add additional
system permissions to the principal if a new service has become available to the signer's applica-
tions. For example, if the Operator installs a org.tourist.PointOfInterest service, it can grant the
ServicePermission[org.tourist.PointOfInterest,GET] and PackagePermission[org.tourist,IMPORT]
to all principals that are allowed to use this service. The Operator can inform the involved parties af-
ter the fact, if at all. This model therefore does not create a bottleneck.
Using digital signing to assign system permissions can therefore delegate the responsibility of provi-
sioning to other parties. The Operator completely defines the limits of the permissions of the princi-
pal, but the signing and deployment can be done by the other parties.
For example, an Operator can define that the ACME company can provision bundles without any
intervention of the Operator. The Operator has to provide ACME once with a signing certificate and
the Operator must associate the ACME principal with the appropriate system permissions on the
device.
The key advantage of this model is the reduced communication between ACME and the Operator:
The Operator can modify the system permissions of ACME applications and be in control at any mo-
ment in time. The ACME company can develop new applications without the need to coordinate
these efforts in any way with the Operator. This model is depicted in Figure 50.5, which also shows
the possible sandboxes for Daffy Inc. and unsigned bundles.
Figure 50.5 Typical Delegation model
Daffy Inc.
sign & deploy
send certificate
unsigned signed by
Daffy set system
signed by permissions
ACME
send certificate
The local permissions can still play an important role in the delegation model because it provides
the signer the possibility to mitigate its risk, just as it did for the Operator. Signers can verify the lo-
cal permissions before they sign a bundle. Like the Operator in the earlier scenario, the signer can
quickly verify the security requirements of a bundle. For example, if a game bundle requests Admin-
Permission[*,*], it is unlikely that the bundle will pass the security audit of the signer. However, in
the unlikely case it did, it will not be granted this permission unless the Operator gave such a per-
mission to the signer's principal on the device.
50.2.4 Grouping
The grouping model is traditionally used because it minimizes the administration of the security
setup. For example, an operator can define the following security levels:
• Untrusted - Applications that are not trusted. These applications must run in a very limited secu-
rity scope. They could be unsigned.
• Trusted - Applications that are trusted but that are not allowed to manage the device or provide
system services.
• System - Applications that provide system services.
• Manage - Applications that manage the device.
The operator signs the bundle with an appropriate certificate before it is deployed, when the bundle
is installed, it will be automatically be assigned to the appropriate security scope.
However, the behavior can also be obtained using the local permissions of a bundle.
For readability, package prefixes that can be guessed are replaced with "..".
The following policy has a condition that limits the permissions to bundles that are signed by
ACME. The permissions given are related to managing other bundles.
ALLOW {
[ ..BundleSignerCondition "* ; o=ACME" ]
The next permission policy is for bundles signed by the operator. The operator bundles get full man-
aging capabilities as well as permissions to provide any service.
ALLOW {
[ ..BundleSignerCondition "*; o=Operator" ]
( ..AdminPermission "*" "*" )
( ..ServicePermission "*" "get,register" )
( ..PackagePermission "*" "import,exportonly" )
} "2"
The following block indicates that all bundles not signed by ACME will not have access to the
com.acme.secret package, nor can they provide it. In this case, only bundles that are signed by
ACME may use the com.acme.secret.* packages. Instead of explicitly specifying all allowed pack-
ages for bundles not signed by ACME, it is easier to deny them the protected packages. The exclama-
tion mark ('!' \u0021) is a parameter for the Bundle Signer Condition to reverse its normal answer.
This facility is also available in the Bundle Location Condition.
That is, the following policy specifies that bundles not signed by ACME will be denied permission to
package com.acme.secret.*.
DENY {
[ ..BundleSignerCondition "* ; o=ACME" "!" ]
( ..PackagePermission "com.acme.secret.*"
"import,exportonly" )
} "3"
Basic permissions define the permissions that are available to all bundles. The basic permissions
therefore have no conditions associated with them so all bundles will be able to use these permis-
sions. All bundles may use the Log Service as well as use any package that was not yet denied earlier.
ALLOW {
(..ServicePermission "..LogService" "get" )
(..PackagePermission "*" "import" )
} "4"
The resulting permissions are summarized in Table 50.1. The + indicates allow, the - means deny.
The number is the deciding policy.
Unsigned
Operator
ACME
..LogService get +4 +4 +2
..ManagedService* register - +1 +2
..ManagedService* get - - +2
com.acme.FooService get - - +2
com.acme.secret import -3 +4 +2
com.acme.secret.bar exportonly -3 - +2
com.acme.foo import +4 +4 +2
bundle signed by ACME start - +1 +2
bundle signed by Operator start - - +2
The system permissions have two possible sources. The system permissions can be bound via the
Permission Admin service to a location. This mechanism is provided for backward compatibility on-
ly. New management applications should use the Conditional Permission Admin service if possible.
If the Permission Admin location is not bound, all the conditional permissions from Conditional Per-
mission Admin act as the system permissions. The relationship between the system permissions
and local permissions is depicted in Figure 50.6.
system permissions
or otherwise
effective
Conditional
permissions Condition[] Permission
Admin
local permissions
Bundle Permission
Resource
During a permission check, the table is traversed in ascending index order and each policy is evalu-
ated. The first policy that is matching controls the outcome of the permission check as given by its
access type. A policy is only matching a permission P when:
ALLOW {
[ ...BundleSignerCondition "cn=*, o=ACME, c=US" ]
[ com.acme.Online ]
(...AdminPermission "*" "*")
}
In the example, both the BundleSignerCondition must be satisfied as well as the com.acme.Online
condition before Admin Permission is granted.
Deny policies significantly simplify the security configuration setup because they handle the com-
mon case of an exception to a general rule. For example, a bundle that is allowed to use all package
imports and exports except packages in the com.acme.secret.* namespace. The set of all possible
packages is impossible to enumerate because it is an infinite set. In this case, * cannot be used be-
cause the com.acme.secret.* should not be included. With a deny policy it is possible to first deny
access to com.acme.secret.* for all bundles bar the exception, and then later allow * for everybody.
The policies for this look like:
DENY {
[...BundleSignerCondition "cn=*, o=ACME" "!" ]
(...PackagePermission "com.acme.secret.*"
"import,exportonly" )
}
ALLOW {
(...PackagePermission "*" "*" )
}
Conditional Bundle
instantiate
PermissionInfo[] Protection
Domain
System wide
policy table
Bundle
instantiate Protection
Domain
Condition objects must always belong to a single Bundle Protection Domain and must never be
shared.
50.5 Conditions
The purpose of a Condition is to decide if a policy is applicable or not. That is, it acts as a guard for
the permissions. The conditions must therefore be evaluated when a Permission object is checked
against the effective permissions of a bundle.
The state of a Condition object can be obtained with its isSatisfied() method. A condition that re-
turns true to this method is called to be satisfied. If the method throws an Exception, this should be
logged and treated as if the condition is not satisfied.
Certain Condition objects could optimize their evaluations if they are activated multiple times in
the same permission check. For example, a user prompt could appear several times in a permission
check but the prompt should only be given once to the user. These conditions are called postponed
conditions, conditions that can be verified immediately are called immediate conditions. The isPost-
poned() method can inform if the condition is immediate or postponed. A Condition must always
return the same value for the isPostponed method so that the Conditional Permission Admin can
cache this value. If this method returns false, the isSatisfied() method must be quick and can be
called during the permission check, otherwise the decision must be postponed until the end of the
permission check because it is potentially expensive to evaluate. Postponed conditions must always
be postponed the first time they are evaluated.
For example, a condition could verify that a mobile phone is roaming. This information is readily
available in memory and therefore the isPostponed() method could always return false. Alterna-
tively, a Condition object that gets an authorization over the network should only be evaluated at
most once during a permission check to minimize the delay caused by the network latency. Such a
Condition object should return true for the isPostponed method so all the Condition objects are eval-
uated together at the end of the permission check.
Condition objects only need to be evaluated multiple times when the answer can change. A Con-
dition object that can vary its satisfiability is called mutable, it can be checked with the isMutable()
method. If the condition is immutable, the Condition object must always return the same result for
the isSatisfied() method. The isMutable() method answers the mutability of the next isSatisfied()
method. The answer of the next call to the isSatisfied method could still differ from the previous
call, even if the isMutable method returns true.
A mutable Condition can become immutable over time but it cannot go from immutable to muta-
ble. Optimizations can take advantage of the immutability by, for example, caching the result of the
isSatisfied() method.
Except for immediate conditions, the isSatisfied method must only be called inside a permission
check.
For example, the Bundle Protection Domain can prune any policy from its view of the policy table
that contains a Condition object that is immutable and not satisfied. The Bundle Signer Condition
and Bundle Location Condition are examples of immutable conditions that can easily be discarded
when they do not match the context bundle when the policy table is instantiated. See Optimizing Im-
mutable Conditions on page 349 for more information about optimizing immutable conditions.
checkPermission current
call stack
SecurityManager
PL will be copied from Ts until the first policy that matches. A matching policy has all of its condi-
tions immediately satisfied and one of the permissions implies permission P. If a policy can never be
matched because it has an immediate condition that cannot be satisfied, then it is not copied to PL.
At the end, PL contains zero or more postponed policies followed by exactly one matching policy.
In pseudo code:
policy:
for each policy T in Ts
for each condition C in T conditions
if C is immediate and C is not satisfied
continue policy
found = false
for permission X in T permissions
found |= X implies P
if not found
continue policy
add T to PL
PL must now be optimized to remove superfluous policies. A postponed policy can be removed if it
cannot change the outcome from the last (which is an immediate) policy. That is, if the immediate
policy at the end has the same access type as the previous policy in PL, then it can be ignored. The
following pseudo code removes these superfluous postponed conditions.
After discarding these superfluous postponed conditions, the contents of PL has the structure out-
line in Figure 50.9, where Tp(x) is a postponed policy with a access type x, and Tm is a matching poli-
cy, ! is the not operator for the condition.
Tm(x)
Tp(x) Tp(!x)
If PL contains only one policy and it is a DENY policy, then the Bundle Protection Domain can direct-
ly answer false from the implies method, which will abort the complete permission check evalua-
tion. In all other cases, it must remember the postponed list PL for the given bundle, and return true.
if PL = {DENY{...}}
return false
Bundle.pl = PL
return true
DENY {
[ BundleSignerCondition "cn=ACME" "!" ]
( FilePermission "/tmp/acme/-" "READ,WRITE" )
} "0"
ALLOW {
( FilePermission "/tmp/-" "READ,WRITE" )
} "1"
ALLOW {
[ PromptCondition "Allowed to Read?" ]
( FilePermission "*" "READ" )
} "2"
DENY {
[ PromptCondition "Deny Writing?" ]
( FilePermission "*" "READ,WRITE" )
} "3"
This setup reserves unconditionally the /tmp/acme/- file system for bundles signed by ACME be-
cause the first line denies any bundle not signed by ACME access to this part of the file system. Read-
ing and writing of the remainder of the /tmp file tree is allowed for all. For the rest of the file system,
read access is prompted to allow, and write access is prompted to deny.
Assume that a bundle signed by ACME wants to read /etc/passwd . Policy 0, and 1 do not match be-
cause the File Permission in these policies are not applicable. Policy 2 has a permission that implies
this file and its condition is postponed, so it will be postponed and policy 3 will also included. There
is no matching policy, so a virtual matching DENY policy (D) will be included as the last entry. This
makes PL: 2, 3, and D.
Tp(ALLOW) # 2
Tp(DENY) # 3
Tm(DENY) # virtual (D)
In this case, there is a superfluous Tp(DENY) #3 because it can not change the final answer of the
last matching DENY. It is therefore removed. The list is thus:
Tp(ALLOW) # 2
Tm(DENY) # virtual
This list must be saved for later evaluation when all the Bundle Protection Domains have finished
successfully.
For example, if bundle A postponed policy Tp1 and bundle B postponed policy Tp2, and bundle C
was immediately satisfied for ALLOW, then the constellation would like Figure 50.10.
Figure 50.10 Evaluation of postponed policies
B postponed Tp2 Tm
C Tm must be ALLOW
The Conditional Permission Admin provides a type specific Dictionary object to all evaluations of
the same postponed Condition implementation class during a single permission check. It is the re-
sponsibility of the Condition implementer to use this Dictionary to maintain states between in-
vocations. The condition is evaluated with a method that takes an array and a Dictionary object:
isSatisfied(Condition[],Dictionary). The array always contains a single element that is the receiver.
An array is used because an earlier version of this specification could verify multiple conditions si-
multaneously.
The Dictionary object has the following qualities:
• It is specific to a Condition implementation class, different implementation classes will not share
this Dictionary object.
• It is created before the isSatisfied(Condition[],Dictionary) is called for the first time during this
permission check.
• It is only valid during the invocation of a single checkPermission session. That is, it is not main-
tained between checkPermission invocations.
• It is shared between invocations of isSatisfied(Condition[], Dictionary) method for different
Bundle Protection Domains.
The algorithm for the postponed processing can now be explained with the following pseudo code:
bundle:
for each bundle B
policy:
for each policy T in B.pl
for C in T conditions
if C is postponed and
C is not satisfied with Dictionary
continue policy
if T access = DENY
return false
else
continue bundle
assert false // can not reach
return true
50.6.4 Example
A permission P is checked while bundle A, B, and C are on the call stack. Their security setup is as fol-
lows:
• PC is a postponed condition,
• P, Q, and R are permissions.
First, the Bundle Protection Domain of bundle C is asked if it implies permission P. Bundle C has
three policies. Policy C1 has no conditions, only a permission that does not imply permission P, it is
therefore ignored. The second policy has an immediate condition IC0, which is not satisfied. There-
fore, the policy's permissions are not even considered. The last policy contains a mutable postponed
condition PC2. The permission P is implied by the related permissions. However, it is not possible to
make the decision at this moment in time, therefore the evaluation of policy C3 is postponed. The
postponed list for bundle C is therefore:
This list can not be optimized because the final access type differs from the earlier access types.
The setup for bundle B is as follows:
Bundle B is considered, its first policy has and immediate Condition object that is IC1. This condi-
tion turns out to be satisfied. This policy is a potential candidate because it has two postponed con-
ditions left. It is a possibility because its permissions imply permission P. The policy is therefore
placed on the postponed list.
Policy B2 is similar, it must also be placed on the postponed list because it implies permission P and
it has a postponed condition PC2.
Policy B3 matches, it is therefore placed on the postponed list and the evaluation is stopped because
there is an immediate decision, therefore it is not necessary to look at policy B4.
There are 2 policies postponed, the bundle is potentially permitted. Bundle's B postponed list there-
fore looks like:
This list cannot be optimized because the final access type differs from the earlier postponed condi-
tions.
Last and least, bundle A.
Bundle A's IC1 is evaluated first and it is satisfied. Permission P is implied by the policy A1's permis-
sions, therefore this policy is postponed for evaluation.
Policy A2 is also satisfied and it directly implies permission P. This policy is therefore also placed on
the postponed list and further evaluation is no longer necessary because it is the first matching poli-
cy. That is, policy A3 is ignored. The postponed list looks like:
ALLOW {} "A2"
After the checkPermission method of the Access Control Context method returns, the Framework
Security Manager must evaluate the postponed lists of all the bundles. The list of postponed policies
looks like Figure 50.10.
Figure 50.11 Evaluation of postponed policies
immediate T0
A
bundle
allow policy
deny policy
condition
postponed T1 T2 T3
B
call stack
postponed T4 T5
C
PC2
The Framework Security Manager must now evaluate the postponed lists for each bundle. In this
example, postponed condition PC2 occurs 3 times. All these evaluations of PC2 get the same Dictio-
nary object. If PC2 prompts the users with a specific question, then it should not ask the same ques-
tion again when another PC2 is evaluated later. The Dictionary object can be used to maintain this
state.
Both PC1 and PC2 prompt the user. PC1 will be rejected in this example, and PC2 will be affirmed.
First the postponed list of bundle A is evaluated. This is the trivial case of ALLOW {}, and the post-
poned list for bundle A succeeds with ALLOW.
For bundle B, policy T1 must prompt for PC2 and PC1. PC2 records the answer in the Dictionary that
is specific for PC2. Because PC1 fails, T1 is not applicable and policy T2 must be evaluated. PC2 had
recorded its answer so it does not prompt but returns true immediately. Policy T2 is an ALLOW policy
and bundle B therefore ends positively.
Last, bundle C requires evaluation of policy T4. PC2 retrieves its answer from the given Dictionary
object and succeeds. Policy T4 has an access type of ALLOW and this concludes the complete permis-
sion check positively.
Manager was called and the user would never be prompted because the failure was detected before
the conditional permissions could be evaluated. However, if the Access Control Context was called
directly, the user would be prompted and fail even if the user acknowledged the request.
* *
<<class>> <<class>>
Conditional Permission
Info Info
Both the ConditionalInfo and PermissionInfo objects can be constructed from encoded strings. The
syntax for these strings are:
The strings are converted by getting the class with the qname, and then creating an instance
through a constructor that takes the given number of arguments. The exclamation mark is conven-
tion for a negated condition, it indicates that the condition should reverse its result. Deny policies
often require the negation of the conditions. For example, often a bundle should not be signed by a
specific signer to exclude it from a resource.
Both the PermissionInfo and ConditionInfo are concrete classes with appropriate methods to con-
struct them from their encoded form. The encoded form given to a Condition implementation con-
structor must not contain the exclamation mark for negation.
A policy is specified with the following syntax:
Matcher m = CP_MATCHER.matcher(text);
int n = 1;
while (m.find()) {
String policy = m.group(1);
ConditionalPermissionInfo info =
admin.newConditionalPermissionInfo( policy );
list.add(info);
}
if ( !update.commit() )
throw new ConcurrentModificationException(
"Conditional Permission Admin was updated concurrently");
}
The Conditional Permission Admin must use reflection to find a public static getCondition method
on the Condition implementation class that takes a Bundle object and a ConditionInfo object as ar-
guments. This method must return a object that implements the Condition interface.
However, this does not have to be a new object, the getCondition method can reuse objects if it so
desires. For example, a Bundle Location Condition is immutable, it therefore maintains only 2 in-
stances: One for bundles that match the given location and one for the others. In the getCondition
method it can verify the bundle's location with argument and return either instance.
This is such a common pattern that the Condition interface provides two such immutable instances:
• TRUE - A condition object that will always evaluate to true and that is never postponed.
• FALSE - A condition object that will always evaluate to false and that is never postponed.
If no static getCondition method can be found, the Conditional Permission Admin service must try
to find a public constructor that takes a Bundle object and a ConditionInfo object as arguments. For
the com.acme.AcmeCondition, the Conditional Permission Admin must look for:
If it is not possible to create a condition object, the given condition must be treated as a
Condition.FALSE object and an error should be logged.
A Condition object will be unique to a Bundle Protection Domain as explained in Encoding versus In-
stantiation on page 335. Thus, any queries made on a Condition object will be with the given Bun-
dle object as context.
The cheapest Condition objects are immutable; they have almost no overhead. If a Condition object
is immutable directly after it is created, then the Framework Security Manager can immediately
shortcut future evaluations. That is, if an immutable Condition object is not satisfied, its parent pol-
icy can be immediately be discarded; it is not even necessary to instantiate any further Condition or
Permission objects for that policy.
Mutable Condition objects must be evaluated during a permission check. Permission checks are
common and the evaluation of a permission should therefore be highly optimized and preferably
not cause additional security checks on the same thread. A mutable condition is system code, it
must be designed to work in a constrained environment. The isSatisfied() method should be de-
signed to quickly return. It should normally base its decision on variables and limit its side effects.
However, side effects are sometimes necessary; a key example is user prompting. As discussed in
Security Manager checkPermission Method on page 337, the evaluation can be postponed towards
the end of the check, where a special version of isSatisfied method is called. The Condition object
must always return true for the isPostponed() method to be postponed and it must always return
the same value.
Mutable postponed conditions must optimize their evaluation by implementing an instance
method isSatisfied(Condition[],Dictionary). This method must only be called with a single element
in the array; this element is unrelated to the given instance (except that the class is the same).
The following is the code for a condition that verifies that an action is granted by a network server.
This is a postponed condition that groups all requests before it asks the host for authorization. The
network code is abstracted in a Host class that is not shown here.
if ( ! host.permits( pending ) )
return false;
granted.addAll( pending );
return true;
}
}
[ HostCondition "payment" ]
The majority of the code is in the isSatisfied method which takes an array of Condition. The con-
structor only stores the action.
This isSatisfied method first gets the set of granted permissions. The first time the method is called
this set does not exist. It is then created and stored in the state dictionary for use in later invocations.
Next, a temporary set pending is created to hold all the actions of the conditions that are checked,
minus any conditions that were already granted during this invocation of the Security Manager
checkPermission method. If the pending list turns out to be empty because all actions were already
granted, the method returns true. Otherwise it asks the host. If the host allows the actions, the pend-
ing actions are added to the granted set in the state dictionary.
The Bundle Signer Condition is immutable and can be completely evaluated during the getCondi-
tion method.
..BundleLocationCondition "http://www.acme.com/*"
..BundleLocationCondition "*://www.acme.com/*"
The Bundle Location Condition is satisfied when its argument can be matched with the actual loca-
tion.
The Bundle Location Condition is immutable and can be completely evaluated during the getCon-
dition method.
// See 1.3.2
Each permission must be listed on its own line using the encoded form of Permission Info. Com-
ment lines are allowed. They consist of lines starting with a # or //, where leading spaces must be ig-
nored. Multiple spaces outside quotes must be treated as a single space.
For example (.. must be replaced with the appropriate package prefix.):
If this resource is present in the Bundle JAR, it will set the local permissions. If it is not present, the
local permissions must be All Permission.
1. If the Permission Admin defines the permissions for bundle A (location is set), then these per-
missions override any Conditional Permission Admin information.
2. If the Conditional Permission Admin has a non-empty table, then this table is used to calculate
the permissions for bundle A.
3. If the default permissions are set in Permission Admin, then these are given to bundle A.
4. All Permission is given to bundle A.
The Permission Admin defines a concept of Default Permissions, which is not supported by Condi-
tional Permission Admin. Default permissions are now modeled with an empty set of conditions.
Empty sets of conditions apply to all bundles, this in addition to any more specific conditions. This is
very different from the Permission Admin service where the default permissions only apply when
there is no location bound permission for that bundle. The default conditions of Permission Admin
are therefore never used when Conditional Permission Admin is present and its table is non-empty.
New applications should use the Conditional Permission Admin service. The Permission Admin ser-
vice will be deprecated in a future release.
• Prompt - The user must be prompted to get the answer, the Conditional Permission Admin will
evaluate the answer to detect if it is satisfied.
• Blanket - The user, during an earlier prompt, has indicated it approves or denies access for that re-
mainder of the lifetime of the bundle. In this state, the Condition object has become immutable.
This specification provides a number of condition classes to bind permission sets to specific bun-
dles. However, custom code can also provide conditions. See Implementing Conditions on page 344
for more information about custom conditions.
ALLOW {
[ ...BundleLocationCondition
"http://www.acme.com/*" ]
( ...SocketPermission "www.acme.com" "connect,accept" )
}
ALLOW {
[ ...BundleLocationCondition
"http://www.et.com/*" ]
[ ...Prompt "Phone home?" ]
( ...SocketPermission "www.et.com" "connect,accept" )
}
50.12.4 Concurrency
A Condition implementation is guaranteed that all evaluations necessary for a single checkPermis-
sion invocation are carried out on the same thread. However, multiple permission checks can take
place on different threads. It is the responsibility of the Condition class implementers to handle
these synchronization issues.
50.13 Security
50.13.1 Service Registry Security
50.13.1.1 Conditional Permission Admin Service
The Conditional Permission Admin service should be part of the Framework and therefore has All
Permission.
50.13.1.2 Client
Clients of the Conditional Permission Admin service that set permissions must themselves have All
Permission because they can give All Permission to any bundle.
50.14 org.osgi.service.condpermadmin
Conditional Permission 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.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.condpermadmin; version="[1.1,2.0)"
50.14.1 Summary
• BundleLocationCondition - Condition to test if the location of a bundle matches or does not
match a pattern.
• BundleSignerCondition - Condition to test if the signer of a bundle matches or does not match a
pattern.
• Condition - The interface implemented by a Condition.
• ConditionalPermissionAdmin - Framework service to administer Conditional Permissions.
• ConditionalPermissionInfo - A list of Permissions guarded by a list of conditions with an access
decision.
• ConditionalPermissionUpdate - Update the Conditional Permission Table.
• ConditionInfo - Condition representation used by the Conditional Permission Admin service.
which to match the bundle location. Matching is done according to the filter string matching rules.
Any '*' characters in the first argument are used as wildcards when matching bundle locations un-
less they are escaped with a '\' character. The Condition is satisfied if the bundle location matches
the pattern. The second argument of the ConditionInfo is optional. If a second argument is present
and equal to "!", then the satisfaction of the Condition is negated. That is, the Condition is satisfied
if the bundle location does NOT match the pattern. If the second argument is present but does not
equal "!", then the second argument is ignored.
□ Constructs a condition that tries to match the passed Bundle's location to the location pattern.
Returns Condition object for the requested condition.
Returns An AccessControlContext that has the Permissions associated with the signer.
The Enumeration returned is based on a copy of the Conditional Permission Table and therefore will
not throw exceptions if the Conditional Permission Table is changed during the course of reading el-
ements from the Enumeration.
Returns An enumeration of the Conditional Permission Infos that are currently in the Conditional Permis-
sion Table.
Deprecated As of 1.1. Use newConditionalPermissionUpdate() instead.
• allow
• deny
commit is called on the returned update, then the call to commit on the returned update will fail.
That is, the commit method will return false and no change will be made to the running Condition-
al Permission Table. There is no requirement that commit is eventually called on the returned up-
date.
Returns A new update for the Conditional Permission Table.
Since 1.1
where access is the access decision, conditions is zero or more encoded conditions, permissions is one or
more encoded permissions and name is the name of the ConditionalPermissionInfo.
name is optional. If name is present in the encoded string, it must quoted, beginning and ending with
". The name value must be encoded for proper parsing. Specifically, the ", \, carriage return, and line
feed characters must be escaped using \", \\, \r, and \n, respectively.
The encoded string contains no leading or trailing whitespace characters. A single space character
is used between access and { and between } and name, if name is present. All encoded conditions and
permissions are separated by a single space character.
Returns The string encoding of this ConditionalPermissionInfo.
Since 1.1
Returns true if the commit was successful. false if the commit did not occur because the Conditional Permis-
sion Table has been modified since the creation of this update.
Throws SecurityException– If the caller does not have AllPermission.
IllegalStateException– If this update's Conditional Permissions are not valid or inconsistent. For ex-
ample, this update has two Conditional Permissions in it with the same name.
• Declare a public static getCondition method that takes a Bundle object and a ConditionInfo ob-
ject as arguments. That method must return an object that implements the Condition interface.
• Implement the Condition interface and define a public constructor that takes a Bundle object and
a ConditionInfo object as arguments.
Concurrency Immutable
where argN are strings that must be encoded for proper parsing. Specifically, the ", \, carriage return,
and line feed characters must be escaped using \", \\, \r, and \n, respectively.
The encoded string contains no leading or trailing whitespace characters. A single space character is
used between type and "arg0" and between the arguments.
Returns The string encoding of this ConditionInfo.
51.1 Introduction
Note: The Permission Admin has been superseded by the Conditional Permission Admin. See Condi-
tional Permission Admin Service Specification on page 325.
In the Framework, a bundle can have a single set of permissions. These permissions are used to veri-
fy that a bundle is authorized to execute privileged code. For example, a FilePermission defines what
files can be used and in what way.
The policy of providing the permissions to the bundle should be delegated to a Management Agent.
For this reason, the Framework provides the Permission Admin service so that a Management Agent
can administrate the permissions of a bundle and provide defaults for all bundles.
Related mechanisms of the Framework are discussed in Security Overview on page 19.
51.1.1 Essentials
• Status information - The Permission Admin Service must provide status information about the
current permissions of a bundle.
• Administrative - The Permission Admin Service must allow a Management Agent to set the per-
missions before, during, or after a bundle is installed.
• Defaults - The Permission Admin Service must provide control over default permissions. These
are the permissions for a bundle with no specific permissions set.
51.1.2 Entities
• PermissionAdmin - The service that provides access to the permission repository of the Frame-
work.
• PermissionInfo - An object that holds the information needed to construct a Permission object.
• Bundle location - The string that specifies the bundle location. This is described in Bundle Identifiers
on page 113.
51.1.3 Operation
The Framework maintains a repository of permissions. These permissions are stored under the bun-
dle location string. Using the bundle location allows the permissions to be set before a bundle is
downloaded. The Framework must consult this repository when it needs the permissions of a bun-
dle. When no specific permissions are set, the bundle must use the default permissions. If no de-
fault is set, the bundle must use java.security.AllPermission. If the default permissions are changed,
a bundle with no specific permissions must immediately start using the new default permissions.
The Permission Admin service is registered by the Framework's system bundle under the
org.osgi.service.permissionadmin.PermissionAdmin interface. This is an optional singleton service,
so at most one Permission Admin service is registered at any moment in time.
The Permission Admin service provides access to the permission repository. A Management Agent
can get, set, update, and delete permissions from this repository. A Management Agent can also use
a SynchronousBundleListener object to set the permissions during the installation or updating of a
bundle.
If any of these conditions is not met, the PermissionInfo object must be ignored and an error mes-
sage should be logged.
The permissions are always set as an array of PermissionInfo objects to make the assignment of all
permissions atomic.
• getLocations() - Returns a list of locations that have permissions assigned to them. This method
allows a Management Agent to examine the current set of permissions.
• getPermissions(String) - Returns a list of PermissionInfo objects that are set for that location, or
returns null if no permissions are set.
• setPermissions(String,PermissionInfo[]) - Associates permissions with a specific location, or re-
turns null when the permissions should be removed.
• getDefaultPermissions() - This method returns the list of default permissions.
• setDefaultPermissions(PermissionInfo[]) - This method sets the default permissions.
can be used to allow a bundle to execute any file in the bundle's persistent storage area.
This only applies to FilePermission objects assigned to a bundle via the setPermission method. This
does not apply to default permissions. A FilePermission for a relative path name assigned via the
setDefaultPermission method must be ignored.
51.3 Security
The Permission Admin service is a system service that can be abused. A bundle that can access and
use the Permission Admin service has full control over the OSGi framework. However, many bun-
dles can have ServicePermission[PermissionAdmin,GET] because all methods that change the state
of the Framework require AdminPermission.
No bundle must have ServicePermission[PermissionAdmin,REGISTER] for this service because only
the Framework should provide this service.
51.4 org.osgi.service.permissionadmin
Permission Admin Package Version 1.2.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.permissionadmin; version="[1.2,2.0)"
51.4.1 Summary
• PermissionAdmin - The Permission Admin service allows management agents to manage the
permissions of bundles.
Returns true if obj is a PermissionInfo, and has the same type, name and actions as this PermissionInfo ob-
ject; false otherwise.
(type)
or
(type "name")
or
where name and actions are strings that must be encoded for proper parsing. Specifically, the ",\, car-
riage return, and line feed characters must be escaped using \", \\, \r, and \n, respectively.
The encoded string contains no leading or trailing whitespace characters. A single space character is
used between type and "name" and between "name" and "actions".
Returns The string encoding of this PermissionInfo.
52.1 Introduction
This specification standardizes the mechanism to extend the Java run-time with new URL schemes
and content handlers through bundles. Dynamically extending the URL schemes that are supported
in an OSGi framework is a powerful concept.
This specification is necessary because the standard Java mechanisms for extending the URL class
with new schemes and different content types is not compatible with the dynamic aspects of an
OSGi framework. The registration of a new scheme or content type is a one time only action in Ja-
va, and once registered, a scheme or content type can never be revoked. This singleton approach to
registration makes the provided mechanism impossible to use by different, independent bundles.
Therefore, it is necessary for OSGi Framework implementations to hide this mechanism and pro-
vide an alternative mechanism that can be used.
52.1.1 Essentials
• Multiple Access - Multiple bundles should be allowed to register ContentHandler objects and
URLStreamHandler objects.
• Existing Schemes Availability - Existing schemes in an OSGi framework should not be overridden.
• life cycle Monitored - The life cycle of bundles must be supported. Scheme handlers and content
type handlers must become unavailable when the registering bundle is stopped.
• Simplicity - Minimal effort should be required for a bundle to provide a new URL scheme or con-
tent type handler.
52.1.2 Entities
• Scheme - An identifier for a specific protocol. For example, "http" is a scheme for the Hyper Text
Transfer Protocol. A scheme is implemented in a java.net.URLStreamHandler sub-class.
• Content Type - An identifier for the type of the content. Content types are usually referred to as
MIME types. A content type handler is implemented as a java.net.ContentHandler sub-class.
• Uniform Resource Locator (URL) - An instance of the java.net.URL class that holds the name of a
scheme with enough parameters to identify a resource for that scheme.
• Factory - An object that creates other objects. The purpose is to hide the implementation types
(that may vary) from the caller. The created objects are a subclass/implementation of a specific
type.
• Proxy - The object that is registered with Java and that forwards all calls to the real implementa-
tion that is registered with the service registry.
• java.net.URLStreamHandler - An instance of the java.net.URLStreamHandler class that can create
URLConnection objects that represent a connection for a specific protocol.
• Singleton Operation - An operation that can only be executed once.
• URLStreamHandlerService - An OSGi service interface that contains the methods of the
URLStreamHandler class with public visibility so they can be called from the Framework.
• AbstractURLStreamHandlerService - An implementation of the URLStreamHandlerService inter-
face that implements the interface's methods by calling the implementation of the super class
(java.net.url.URLStreamHandler). This class also handles the setting of the java.net.URL object
via the java.net.URLStreamHandlerSetter interface.
• URLStreamHandlerSetter - An interface needed to abstract the setting of the java.net.URL object.
This interface is related to the use of a proxy and security checking.
• java.net.URLStreamHandlerFactory - A factory, registered with the java.net.URL class, that is used
to find java.net.URLStreamHandler objects implementing schemes that are not implemented
by the Java environment. Only one java.net.URLStreamHandlerFactory object can be registered
with Java.
• java.net.URLConnection - A connection for a specific, scheme-based protocol. A
java.net.URLConnection object is created by a java.net.URLStreamHandler object when the
java.net.URL.openConnection method is invoked.
• java.net.ContentHandler - An object that can convert a stream of bytes to a Java object. The class of
this Java object depends on the MIME type of the byte stream.
• java.net.ContentHandlerFactory - A factory that can extend the set of java.net.ContentHandler ob-
jects provided by the java.net.URLConnection class, by creating new ones on demand. Only one
java.net.ContentHandlerFactory object can be registered with the java.net.URLConnection class.
• MIME Type - A namespace for byte stream formats. See [2] MIME Multipurpose Internet Mail Exten-
sion.
The following class diagram is surprisingly complex due to the complicated strategy that Java uses
to implement extendable stream handlers and content handlers.
is called by
AbstractURL java.net.URL
Stream
HandlerServ.
1
gets URLStreamHandlers
from
0..1
<<interface>> java.net.URL java.net.URL java.net.Content
0..* URLStream StreamHandler 0..*
Connection Handler
HandlerServ. Factory
1
gets content via
setURL
0..1
java.net.URL java.net.Content
<<interface>>
URLStream
HandlerSetter
52.1.3 Operation
A bundle that can implement a new URL scheme should register a service object under the
URLStreamHandlerService interface with the OSGi Framework. This interface contains public ver-
sions of the java.net.URLStreamHandler class methods, so that these methods can be called by the
proxy (the object that is actually registered with the Java run-time).
The OSGi Framework implementation must make this service object available to the underlying
java.net implementation. This must be supported by the OSGi Framework implementation because
the java.net.URL.setStreamHandlerFactory method can only be called once, making it impossible to
use by bundles that come and go.
Bundles that can convert a content-typed stream should register a service object under the name
java.net.ContentHandler. These objects should be made available by the OSGi Framework to the
java.net.URLConnection class.
Both problems impact the OSGi operating model, which allows a bundle to go through different life
cycle stages that involve exposing services, removing services, updating code, replacing services pro-
vided by one bundle with services from another, etc. The existing Java mechanisms are not compati-
ble when used by bundles.
The Content Handler Factory is implemented using a similar technique and has therefore the same
problems.
To facilitate the discovery of built-in handlers that are available through the name construction,
the method described in the next section must be used by the Framework before any handlers are
searched for in the service registry.
org.osgi.impl.handlers | com.acme.url
The package names are the prefixes that are put in front of a scheme or content type to form a class
name that can handle the scheme or content-type.
A URL Stream Handler name for a scheme is formed by appending the string ".Handler" to the
scheme name. Using the packages in the previous example, the rsh scheme handler class is searched
by the following names:
org.osgi.impl.handlers.rsh.Handler
com.acme.url.rsh.Handler
MIME type names contain the solidus ('/' \u002F) character and can contain other characters that
must not be part of a Java class name. A MIME type name must be processed as follows before it can
be converted to a class name:
1. First, all solidi in the MIME name must be converted to a full stop ('.' \u002E). All other charac-
ters that are not allowed in a Java class name must be converted to an underscore ('_' \u005F).
application/zip application.zip
text/uri-list text.uri_list
image/vnd.dwg image.vnd_dwg
2. After this conversion, the name is appended to the list of packages specified in
java.content.handler.pkgs. For example, if the content type is application/zip, and the packages
are defined as in the previous example, then the following classes are searched:
org.osgi.impl.handlers.application.zip
com.acme.url.application.zip
The Java run-time specific packages should be listed in the appropriate properties so that implemen-
tations of the URL Stream Handler Factory and Content Handler Factory can be made aware of these
packages.
class URLStreamHandlerImpl {
...
protected URLStreamHandlerSetter realHandler;
...
public void parseURL(
URLStreamHandlerSetter realHandler,
URL u, String spec, int start, int limit) {
this.realHandler = realHandler;
parseURL(u, spec, start, limit);
}
protected void setURL(URL u,
String protocol, String host,
int port, String authority,
String userInfo, String path,
String query,String ref) {
realHandler.setURL(u, protocol, host,
port, authority, userInfo, path,
query, ref);
}
...
}
The URLStreamHandler.parseURL method will call the setURL method which must be invoked
on the proxy rather than this. That is why the setURL method is overridden to delegate to the
URLStreamHandlerSetter object in realHandler as opposed to super.
52.7 org.osgi.service.url
URL Stream and Content Handlers Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.url; version="[1.0,2.0)"
52.7.1 Summary
• AbstractURLStreamHandlerService - Abstract implementation of the URLStreamHandlerSer-
vice interface.
• URLConstants - Defines standard names for property keys associated with URLStreamHan-
dlerService and java.net.ContentHandler services.
• URLStreamHandlerService - Service interface with public versions of the protected
java.net.URLStreamHandler methods.
• URLStreamHandlerSetter - Interface used by URLStreamHandlerService objects to call the se-
tURL method on the proxy URLStreamHandler object.
52.7.2.9 public void parseURL(URLStreamHandlerSetter realHandler, URL u, String spec, int start, int limit)
realHandler The object on which the setURL method must be invoked for the specified URL.
□ Parse a URL using the URLStreamHandlerSetter object. This method sets the realHandler field with
the specified URLStreamHandlerSetter object and then calls parseURL(URL,String,int,int).
See Also java.net.URLStreamHandler.parseURL
52.7.2.11 protected void setURL(URL u, String proto, String host, int port, String file, String ref )
□ This method calls realHandler.setURL(URL,String,String,int,String,String).
See Also java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)
Deprecated This method is only for compatibility with handlers written for JDK 1.1.
52.7.2.12 protected void setURL(URL u, String proto, String host, int port, String auth, String user, String path, String
query, String ref )
□ This method calls realHandler.setURL(URL,String,String,int,String,String,String,String) .
See Also java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)
The values associated with these keys are of type java.lang.String[] or java.lang.String, unless other-
wise indicated.
Provider Type Consumers of this API must not implement this type
52.7.4.7 public void parseURL(URLStreamHandlerSetter realHandler, URL u, String spec, int start, int limit)
realHandler The object on which setURL must be invoked for this URL.
□ Parse a URL. This method is called by the URLStreamHandler proxy, instead of
java.net.URLStreamHandler.parseURL, passing a URLStreamHandlerSetter object.
See Also java.net.URLStreamHandler.parseURL
52.7.5.1 public void setURL(URL u, String protocol, String host, int port, String file, String ref )
See Also java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)
Deprecated This method is only for compatibility with handlers written for JDK 1.1.
52.7.5.2 public void setURL(URL u, String protocol, String host, int port, String authority, String userInfo, String path,
String query, String ref )
See Also java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)
52.8 References
[1] URLs
http://www.ietf.org/rfc/rfc1738.txt
[2] MIME Multipurpose Internet Mail Extension
http://www.nacs.uci.edu/indiv/ehood/MIME/MIME.html
[3] Assigned MIME Media Types
http://www.iana.org/assignments/media-types
53.1 Introduction
The module layer is responsible for the resolve operation that wires requirements (Import-Package,
Require-Bundle etc.) to capabilities (Export-Package, Bundle-SymbolicName/Bundle-Version etc.).
The resolve operation is designed to work stand-alone but in certain use cases it is important to be
able to influence the resolver's decisions. This specification defines a Resolver Hook Factory service
that allows third party bundles to influence the resolve operation. Primary use cases for this hook
are scoping of groups of bundles. However, the hooks also allows bundle to find out about, and con-
trol, the resolve operation for other purposes.
53.1.1 Essentials
• Reduction - Allow third party bundles to remove capabilities from a set of capabilities that match-
es a requirement.
• Complete - Support all built-in namespaces as well as the generic capability and requirement
headers.
• Singletons - Allow third party bundles to remove candidates from a set of singleton capabilities
before the resolver selects one.
• Secure - Support full security but allow operation without security present.
53.1.2 Entities
• Resolver Hook Factory - The service registered by a bundle that wants to control the resolve opera-
tion. This service is used to create an instance of the Resolver Hook for each resolve operation.
• Resolver Hook - Is created by the Resolver Hook Factory service for each resolver process. Is con-
sulted to reduce candidate capabilities for resolving and selecting singletons.
• Client - A bundle that is considered during the resolve operation.
• Handler - A bundle that registers a Resolver Hook Factory service for influencing the resolve oper-
ation.
• Bundle Capability - A capability represents a feature of a bundle described with attributes and di-
rectives defined in a namespace. Some namespaces are built-in to the OSGi framework, others
are generic.
• Bundle Requirement - A requirement represents a need from a bundle described as a filter on the at-
tributes of a Bundle Capability.
• Provider - A bundle that provides a Bundle Capability.
• Consumer - A bundle that requires a Bundle Capability
• Resolver - The internal framework machinery that resolves requirements to providers with
matching capabilities.
Resolver
Find HookHook
Impl Resolver Hook
Impl Factory Impl
<<interface>> <<service>>
Resolver Hook 0..n 1 Resolver Hook
Factory
0..n 0..n
1
Resolver Impl
1
53.1.3 Synopsis
A handler bundle that needs to manage the wiring between bundles must register a Resolver Hook
Factory service. For each resolve operation the Resolver needs to perform, the framework asks each
Resolver Hook Factory service for a new Resolver Hook specific for the operation. During the resolve
operation, the Resolver will allow the Resolver Hooks to remove candidate solutions and assist in se-
lecting singletons.
• Root Bundle - Calling certain methods on a bundle when a bundle is in the INSTALLED state will
cause the framework to begin a resolve operation in order to resolve the bundle. In general, a bun-
dle needs to be resolved when its class loader is needed. The following Bundle methods will start
a resolve operation when the subject is not yet resolved:
• start
• loadClass
• findEntries
• getResource
• getResources
• Resolve Bundles - The set of bundle revisions of the unresolved bundles given as argument, or their
default when null is used, to the Framework Wiring resolveBundles method. See Using the Wiring
API on page 158.
• Refresh Bundles - A refresh operation will have to re-resolve the bundles that will be unresolved in
the refresh. The trigger bundles are then the bundle revisions of the dependency closure, which
is described in Refreshing on page 167.
• Dynamic Import - A Dynamic Import can require the framework to start a resolve operation.
• Other - The Resolver Hook is a service so other parties can to start a resolver operation to run
what-if scenarios or for other purposes.
• Static - A static bundle resolve operation. This resolve operation is necessary any time one or
more bundles transitions from the INSTALLED state to the RESOLVED state. During this resolve
operation the framework attempts to resolve static requirements specified by the bundles being
resolved.
• Dynamic - A dynamic import must be resolved.
The resolve operation is not limited to the trigger bundles only, they just provide the root bundles
that must be resolved. The Resolver is free to consider any present bundle to provide the required ca-
pabilities. If such bundles are in the INSTALLED state then they can also become a candidate to be re-
solved. The resolver is also free to use bundles that are actually not installed in the framework, for
example for what-if scenarios.
• filterResolvable(Collection) - Removes bundles that are candidates for resolving so they do not
resolve in the current operation. Provides an easy way to exclude bundles.
• filterMatches(BundleRequirement,Collection) - Remove matching capabilities from the candi-
date capabilities. This effectively hides capabilities for certain requirers.
• filterSingletonCollisions(BundleCapability,Collection) - Remove potentially conflicting single-
tons from the collection. This provides the possibility to resolve a singleton multiple times in dif-
ferent groups.
A Resolver Hook can influence the outcome of a resolve operation by removing entries from shrink-
able collections. A shrinkable collection is a collection that can only shrink. The Handler can re-
move entries from the collection but it cannot add an entry to it. Any attempt to add to the collec-
tion must result in throwing an Unsupported Operation Exception. All collections in the Resolver
Hook API are shrinkable collections.
The Resolver Hook Factory services begin(Collection) method is called in the ranking order, see Ser-
vice Ranking Order on page 139. This is the same order used for calling the resulting Resolver Hooks.
The Resolver Hook end() method notifies the Handler that the resolve operation has finished. The
framework must not hold on to this Resolver Hook instance after the end() method has been called.
if ( group.contains(other) ||
system.contains(other) )
continue;
The framework can call this method multiple times for the same singleton capability. For exam-
ple, as a first pass a framework may want to determine if a singleton bundle is resolvable first based
on the presence of other already resolved singleton capabilities. Later the framework may call this
method again to determine which singleton capabilities from unresolved bundles to allow to re-
solve.
1. Collect a snapshot of registered Resolver Hook Factory services that will be called during the cur-
rent resolve operation. If a Resolver Hook Factory contained in the snapshot unregisters then the
resolve must fail, see Failures on page 388. Each registered Resolver Hook Factory service in
the snapshot will be obtained by the framework through the system's bundle context.
2. For each Resolver Hook Factory in the snapshot, in ranking order, call the begin(Collection)
method to inform the Handler about the begin of a new resolve operation. This method must re-
turn a Resolver Hook. If this hook is not null, must be added to list H. If a corresponding Resolver
Hook Factory service is unregistered then the Resolver Hook must be removed from H.
3. Determine the collection of unresolved bundle revisions that may be considered for resolving
during the current resolve operation and place each of the bundle revisions in a shrinkable col-
lection U(nresolved).
• For each active Resolver Hook in H(ooks), call the filterResolvable(Collection) method with
U. The Handler can remove any candidate that should not be resolved.
U now contains all the unresolved bundle revisions that potentially could be resolved during
this resolve operation. Any bundle revisions that were removed by Handlers must not resolve in
this operation.
This step can be repeated multiple times interspersed with other calls except to the begin and
end methods.
4. S = {}
5. For each bundle revision B in U that represents a singleton capability:
• Determine the collection of available capabilities that have a namespace of
osgi.wiring.bundle, are singletons, and have the same symbolic name as the singleton bundle
revision B and place each of the matching capabilities into a shrinkable collection S.
• Remove the osgi.wiring.bundle capability provided by the bundle revision B from S. A single-
ton bundle cannot collide with itself.
• For each resolver hook call the filterSingletonCollisions(BundleCapability,Collection)
method with the osgi.wiring.bundle capability provided by bundle revision B and S.
S now contains all the singleton osgi.wiring.bundle capabilities that can influence the ability of
bundle revision B to resolve.
This step can be repeated multiple times interspersed with other calls except to the begin and
end methods.
6. During a resolve operation the Resolver can resolve any or all bundles contained in U. For each
bundle revision B in U which the Resolver attempts to resolve the following steps must be fol-
lowed:
• For each requirement R(equirement) specified by bundle revision B, determine the collec-
tion of capabilities that satisfy the requirement R and place each matching capability into a
shrinkable collection C(apabilities). A capability is considered to satisfy a particular require-
ment if its attributes match the requirement's filter and the requirer bundle has permission
to access the capability.
• For each Resolver Hook in H, call the filterMatches(BundleRequirement,Collection) method
with the Bundle Requirement R and the shrinkable collection C.
C now contains all the capabilities that can be used to satisfy the requirement R. Any other capa-
bilities that got removed from C must not be used to satisfy requirement R.
This step can be repeated multiple times interspersed with other calls except begin and end.
7. For each Resolver Hook in H
• Call the end method to inform the Handler about a resolve operation ending.
8. For each Resolve Hook still in H, ensure that the Resolver Hook is no longer referenced.
In cases where the a shrinkable collection becomes empty the framework must continue calling the
remaining hooks because these hooks can also be used to trace progress.
The above steps are meant to illustrate how the Resolve Hooks are used by the Resolver, they are not
normative. The nature of the resolve operation and the Resolver algorithm can require back track-
ing by the Resolver implementation. It is therefore acceptable for the Resolver to call the Resolver
Hook multiple times with similar or identical parameters during a single resolve operation. This is
true for all methods except the begin and end methods that are only called once during a resolve op-
eration.
A Resolver Hook must always return the same answer for the same set of inputs, that is, it must be
stable.
53.3.2 Failures
If during the resolving anything goes wrong then the Resolver must abort the resolve operation,
clean up and report an error.
If the begin(Collection) method successfully returns a ResolverHook, then the end() method must
be called on that hook if it is still valid (its ResolverHookFactory is still registered) at the end of the
Resolve. A ResolverHook can therefore safely allocate resources in the begin(Collection) method be-
cause it is guaranteed that it can deallocate them in the end() method.
The following are potential failures:
If the Resolver fails, it must throw a Bundle Exception to the caller if possible. Otherwise it must
publish a Framework Event of type ERROR.
53.4 Security
The Resolver Hook Factory service described in this specification is a highly complex facility that
requires great care in their implementation to maintain the Framework invariants. It is therefore
important that in a secure system the permission to register these hooks is only given to privileged
bundles.
In this case, the user of the Resolver Hook Factory service is the framework. Therefore, there is never
a need to provide this service. Implementers of these hooks must have:
53.5 org.osgi.framework.hooks.resolver
Framework Resolver Hooks Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.hooks.resolver; version="[1.0,2.0)"
53.5.1 Summary
• ResolverHook - OSGi Framework Resolver Hook instances are obtained from the OSGi Frame-
work Resolver Hook Factory service.
• ResolverHookFactory - OSGi Framework Resolver Hook Factory Service.
The following steps outline the way a framework uses the resolver hooks during a resolve process.
1. Collect a snapshot of registered resolver hook factories that will be called during the current re-
solve process. Any hook factories registered after the snapshot is taken must not be called dur-
ing the current resolve process. A resolver hook factory contained in the snapshot may become
unregistered during the resolve process. The framework should handle this and stop calling
the resolver hook instance provided by the unregistered hook factory and the current resolve
process must fail. If possible, an exception must be thrown to the caller of the API which trig-
gered the resolve process. In cases where the caller is not available a framework event of type er-
ror should be fired.
2. For each registered hook factory call the ResolverHookFactory.begin(Collection) method to in-
form the hooks about a resolve process beginning and to obtain a Resolver Hook instance that
will be used for the duration of the resolve process.
3. Determine the collection of unresolved bundle revisions that may be considered for resolution
during the current resolution process and place each of the bundle revisions in a shrinkable col-
lection Resolvable. For each resolver hook call the filterResolvable(Collection) method with the
shrinkable collection Resolvable.
4. The shrinkable collection Resolvable now contains all the unresolved bundle revisions that may
end up as resolved at the end of the current resolve process. Any other bundle revisions that got
removed from the shrinkable collection Resolvable must not end up as resolved at the end of the
current resolve process.
5. For each bundle revision B left in the shrinkable collection Resolvable and any bundle revision B
which is currently resolved that represents a singleton bundle do the following:
• Determine the collection of available capabilities that have a namespace of osgi.identity, are
singletons, and have the same symbolic name as the singleton bundle revision B and place
each of the matching capabilities into a shrinkable collection Collisions.
• Remove the osgi.identity capability provided by bundle revision B from shrinkable collection
Collisions. A singleton bundle cannot collide with itself.
• For each resolver hook call the filterSingletonCollisions(BundleCapability, Collection) with
the osgi.identity capability provided by bundle revision B and the shrinkable collection Colli-
sions
• The shrinkable collection Collisions now contains all singleton osgi.identity capabilities that
can influence the ability of bundle revision B to resolve.
• If the bundle revision B is already resolved then any resolvable bundle revision contained in
the collection Collisions is not allowed to resolve.
6. During a resolve process a framework is free to attempt to resolve any or all bundles contained
in shrinkable collection Resolvable. For each bundle revision B left in the shrinkable collection
Resolvable which the framework attempts to resolve the following steps must be followed:
• For each requirement R specified by bundle revision B determine the collection of capabilities
that satisfy (or match) the requirement and place each matching capability into a shrinkable
collection Candidates. A capability is considered to match a particular requirement if its at-
tributes satisfy a specified requirement and the requirer bundle has permission to access the
capability.
• For each resolver hook call the filterMatches(BundleRequirement, Collection) with the re-
quirement R and the shrinkable collection Candidates.
• The shrinkable collection Candidates now contains all the capabilities that may be used to
satisfy the requirement R. Any other capabilities that got removed from the shrinkable col-
lection Candidates must not be used to satisfy requirement R.
7. For each resolver hook call the end() method to inform the hooks about a resolve process end-
ing.
In all cases, the order in which the resolver hooks are called is the reverse compareTo ordering of
their Service References. That is, the service with the highest ranking number must be called first. In
cases where a shrinkable collection becomes empty the framework is required to call the remaining
registered hooks.
Resolver hooks are low level. Implementations of the resolver hook must be careful not to create an
unresolvable state which is very hard for a developer or a provisioner to diagnose. Resolver hooks al-
so must not be allowed to start another synchronous resolve process (e.g. by calling Bundle.start() or
FrameworkWiring.resolveBundles(Collection) ). The framework must detect this and throw an Ille-
galStateException.
See Also ResolverHookFactory
Concurrency Not Thread-safe
This method can filter the list of collision candidates by removing potential collisions. Removing a
collision candidate will allow the specified singleton to resolve regardless of the resolution state of
the removed collision candidate.
• start
• loadClass
• findEntries
• getResource
• getResources
In such cases the collection will contain the single bundle which the framework is trying to resolve.
Other cases will cause multiple bundles to be included in the trigger bundles collection. When re-
solveBundles is called the collection of triggers must include all the current bundle revisions for
bundles passed to resolveBundles which are in the INSTALLED state.
When FrameworkWiring.refreshBundles(Collection, org.osgi.framework.FrameworkListener...) is
called the collection of triggers is determined with the following steps:
As described above, a resolve process is typically initiated as a result of calling API that causes the
framework to attempt to resolve one or more bundles. The framework is free to start a resolve
process at any time for reasons other than calls to framework API. For example, a resolve process
may be used by the framework for diagnostic purposes and result in no bundles actually becom-
ing resolved at the end of the process. Resolver hook implementations must be prepared for resolve
processes that are initiated for other reasons besides calls to framework API.
Returns a resolver hook instance to be used for the duration of the resolve process. A null value may be re-
turned which indicates this resolver hook factory abstains from the resolve process.
54.1 Introduction
The basic framework provides complete visibility for any bundle to any other bundle. In certain use
cases it can be important to provide the impression to application bundles that they are part of a
limited group of bundles. Bundle Hook services allow Handlers to hide bundles from other bundles
by filtering the Bundle Events and return values of methods that return bundles.
Though Bundle Hooks can effectively control bundle visibility of other bundles by filtering some of
the key Bundle Context methods as well as event delivery, it does not provide proper isolation. Bun-
dles that use other API will be able to see bundles even if they are hidden by the Bundle Hooks.
54.1.1 Essentials
• Filtering - Remove bundles from the view of specific bundles.
54.1.2 Entities
• Find Hook - A service used by the framework to filter methods that return bundles.
• Event Hook - A service used by the framework to filter Bundle Events before they are delivered to
their listeners.
• Collision Hook - A service used by the framework to filter colliding bundles during an install or
update operation when the org.osgi.framework.bsnversion is set to managed.
• Collision - Two bundles collide when they have the same version and bundle symbolic name.
• Client - The bundle that finds bundles or receives events about bundles.
• Handler - The bundle that registers a hook service.
• Target - The bundle performing the install or update operation.
1 1 1
Framework
Impl
54.1.3 Synopsis
A Handler registers Bundle Hook services to filter the view on the bundles stored in the framework.
Whenever the framework has to deliver Bundle events to one or more bundles the Event Hook ser-
vices are asked to look at the target bundles and remove any targets from the collection. Removed
bundles are then not notified.
If a bundle calls a method that returns a bundle like the Bundle Context getBundles method or the
getBundle method, the Find Hook is called. The Find Hook can then look at the bundles that will be
returned to the caller and filter that list accordingly.
If the Framework installs or updates a bundle it is possible that the new bundle symbolic name/ver-
sion pair collides with an existing bundle. The org.osgi.framework.bsnversion property controls the
property in this case. The Collision Hook is used to control this policy when the property is set to
managed.
There can be multiple Bundle Hook services registered by different Handlers, multiple Bundle Hook
services are called in service ranking order.
As a best practice a Handler should not hide a Bundle from itself. That is, its own events should al-
ways be received and if it gets the bundles from the framework its own Bundle object should be in-
cluded.
A Handler must register a bundle Event Hook service to intercept and filter events before they are
delivered to bundles. The framework must call the event(BundleEvent,Collection) method on all
registered hooks in service ranking order to filter the events before they are delivered to any of the
registered bundle listeners. The Handler can remove any BundleContext objects from the given
shrinkable collection it wants shield from the event's Bundle.
The event method must be called once for each Bundle Event, this includes Bundle Events that are
generated when there are no Bundle Listeners registered.
The event(BundleEvent,Collection) method must be called on the same thread that is performing
the action which generated the specified event. The shrinkable collection includes BundleContext
objects with all Bundle Listeners registered with them.
A Bundle Event Hook must receive all Bundle Events:
• INSTALLED
• RESOLVED
• STARTING
• STARTED
• STOPPING
• STOPPED
• UNRESOLVED
• UPDATED
• UNINSTALLED
• Other if new events are defined in later versions
• getBundle(long)
• getBundles()
• getBundle(String) - If the caller knows the name then it is not necessary to hide the bundle.
The Bundle Find Hook is also used during an install operation when the to be installed bun-
dle is already installed at a given location. Normally, the install the returns the Bundle object
of the existing bundle but this can cause confusion for the installer when this bundle is hidden
by the Find Hook. Therefore, the REJECTED_BY_HOOK Bundle Exception is thrown when the
find(BundleContext,Collection) method determines that the Bundle Context has no visibility of the
conflicting bundle.
• single - Collisions are not allowed, attempting to install/update a bundle that will cause a colli-
sion is rejected and all bundles can assume there are no collisions between installed bundles.
• multiple - Collisions are allowed and bundles must assume that there are collisions in the set of
installed bundles.
• managed - Collisions are managed via a Collision Hook service, specified in the remainder of this
section.
There are two types of operation that can create a new bundle revision: Install and Update. During this
creation the framework has to consider its bsnversion policy as defined by the launching proper-
ty. For each creation, there are a number of candidates to collide with. In single mode, any candidate
that exists will fail the creation. In multiple mode, any number of candidates are allowed. In man-
aged mode, no candidates are allowed, like the single mode, but the Collision Hook services can
prune the list of candidates before the framework makes the decision. If the Collision Hook services
have emptied the list of candidates then the installation will succeed, if any bundle remains in this
list then the operation fails. In managed mode, creations are treated as in single mode but bundles
must assume as if the system operates in multiple mode.
The purpose of the Collision Hook is to delegate the decision of bundle collisions to a management
agent. For example, using this and other hooks a management agent can create regions of bundles
that have limited visibility of each other. Since these bundles do not have visibility of all other bun-
dles a global collision does not necessarily translate into a collision inside a region. Using the Colli-
sion Hook the management agent can allow these collisions globally but restrict their impact local-
ly.
In managed mode the framework must call all registered Collision Hook services for each bundle
install and update operation. The calling order of the hooks is defined by ranking order, see Service
Ranking Order on page 139. The Collision Hook service is only called in managed mode and there ex-
ists one or more candidates during the creation phase of an install/update operation.
The CollisionHook interface has a single method:
The filterCollisions(int,Bundle,Collection) method takes a type of operation value that must be one
of the following two values that indicate the operation that caused the Collision Hook to be called:
• INSTALLING
• UPDATING
54.6 Security
All hooks described in this specification are highly complex facilities that require great care in their
implementation to maintain the Framework invariants. It is therefore important that in a secure
system the permission to register these hooks is only given to privileged bundles.
In this case, the user of the hook services is the framework. Therefore, there is never a need to pro-
vide:
• ServicePermission[..EventHook,GET], or
• ServicePermission[..FindHook,GET], or
• ServicePermission[..CollisionHook,GET]
54.7 org.osgi.framework.hooks.bundle
54.7.1 Summary
• CollisionHook - OSGi Framework Bundle Collision Hook Service.
• EventHook - OSGi Framework Bundle Event Hook Service.
• FindHook - OSGi Framework Bundle Context Hook Service.
• installing - The target is the bundle associated with the BundleContext used to call one of the in-
stall methods. The collision candidate collection contains the existing bundles installed which
have the same symbolic name and version as the bundle being installed.
• updating - The target is the bundle used to call one of the update methods. The collision candi-
date collection contains the existing bundles installed which have the same symbolic name and
version as the content the target bundle is being updated to.
This method can filter the collection of collision candidates by removing potential collisions. For
the specified operation to succeed, the collection of collision candidates must be empty after all reg-
istered collision hook services have been called.
Bundles registering this service will be called during framework lifecycle (install, start, stop, update,
and uninstall bundle) operations.
Concurrency Thread-safe
55.1 Introduction
The OSGi framework has built-in support for the normal service primitives: publish, find, and bind.
Despite their simplicity, these primitives are surprisingly powerful and have become quite popular.
However, these primitives operate on information that is not completely visible to the bundles. For
example, it is impossible to find out what services are being waited upon by other bundles. This in-
formation can be useful to provide a service just in time to that bundle. Additionally, it is also not
possible to allow bundles functionality that interacts with the service engine. For example, a bun-
dle could proxy another service but to do this transparently, it is required to hide the original service
and offer the proxy only to a specific bundle. With the current primitives this is also not possible.
Therefore, this service hook specification provides a number of new mechanisms that closely in-
teract with the service engine. These interactions are not intended for use by application bundles.
The service primitives appear simple but require surprisingly complex code to make them appear
simple to the bundle developer. Modifying the behavior of the service engine requires developers to
closely follow the semantics of the OSGi service model and this is often hard, requiring a significant
amount of code.
However, the service hooks provide a more symmetric model for service based programming that
can act as a multiplier for the framework. The basic framework provides a powerful service engine
and this specification allows a bundle to interact with this service engine
55.1.1 Essentials
• Robust - The service primitives are very simple and work reliably in many scenarios. The speci-
fied hooks interact with this robust service engine. This interaction must not cause disruption of
the normal operations.
• Find listeners - Provide information about the services specific bundles are interested in.
• Control visibility - Provide a mechanism to hide the visibility of a service to one or more bundles.
• Intercept finds - Provide a mechanism to detect the searches of a bundle in the service registry and
restrict the set of found service references.
• Whiteboard based - Use the [1] Whiteboard Pattern to simplify the writing of the interceptors.
55.1.2 Entities
• Client - The bundle that finds services, gets services, and/or receives events about services.
• Handler - The bundle that registers a hook service and uses this to view or modify the state.
• Target - A client bundle being targeted by a Handler.
• Publisher - A client bundle that publishes services.
• Consumer - A client bundle that consumes services.
• Service Engine - The internal framework machinery that makes the service registry work.
• Event Listener Hook - An Event Listener Hook intercepts service events before they are delivered to
the client. The hook can select to remove events for specific bundles, which effective allows the
hook to hide service events from a bundle.
• Find Hook - A find hook intercepts the getServiceReference(s) call just before it is returns the re-
sult to the client. The result can be influenced by removing service entries. The find hook can be
used to hide specific services for specific bundles.
• Listener Hook - The listener hook provides insight into what services are being waited for in the
system. It gets updated as service listeners are added and removed from the service registry.
1 1 1
Framework
Impl
55.1.3 Synopsis
A bundle that needs to hide service references from other bundles, or wants to be informed about
the service events another bundle sees, can register a Find and Event Listener hook by registering a
Find Hook service and an Event Listener Hook service with the framework. If a service event is gen-
erated, it will pass this event to the hook. The Event Listener Hook method can then inspect the ar-
guments and optionally remove bundles from the event delivery list.
When a bundle uses the Bundle Context getServiceReference or getServiceReferences method, the
Find Hook is notified with the list of discovered services. The hook can then remove any service ref-
erences it wants to hide for the target bundle.
A bundle that wants to be aware of the services bundles are waiting for to be registered can register a
Listener Hook. The framework will notify such hooks of all existing listeners as well as any changes
in this list. The interceptor can use the filter information registered with the listener to detect the
services that are being listened for.
55.3.1 Proxying
In an OSGi system, all communication is normally tunneled through services. This makes it a very
interesting place for a handler to intercept the service communications. These handlers can provide
facilities like proxying, extra security, authentication, and other functions completely transparent
to the parties that interact through services.
Proxying an existing service for a specific bundle requires the following steps:
Registering a proxy service X' is trivial with the OSGi API, there are no special requirements on the
service. As long as it implements the listed interfaces and provides the same attributes then it can
pose as service X.
Hiding service X can be implemented with a combination of the Event Listener Hook and the Find
Hook. The Event Listener Hook can be used to hide any service events from the target bundle and
the Find Hook can be used to remove X from the delivered results of the getServiceReference(s)
methods.
In the following figure the difference between a normal service interaction and a proxied interac-
tion is depicted. In the normal case, Bundle A directly uses Service X, in the proxying case, the Proxy
Bundle hides the original and provides an alternative.
Bundle B Bundle B
However, there is one complication with the service hiding: what is the observing state of the tar-
get bundle when proxying begins? The Event Listener Hook must be registered to act as a filter on
the service events. Just after this registration it can not determine what events have been seen by
the target bundle. If it has already checked out X, the hook has no possibility to make the target bun-
dle unget the service. A solution is to transiently stop the target bundle before the hook is registered
and then transiently started it again, if the bundle is active. It is usually not advised to start/stop oth-
er bundles but this seems to be the only reliable solution. The problem can be alleviated when the
start level is used to start the proxying handler bundle before the target bundles, in that case the tar-
get bundle is not started when the proxy is created. Though this optimizes the normal case, stop-
ping the target bundle remains necessary because any of the bundles can be updated or stopped at
any moment in time.
The following example shows how to hide a specific Service Reference from a specific bundle.
Hide(BundleContext context,
ServiceReference reference,
Bundle bundle) {
this.context = context;
this.bundle = bundle;
this.reference = reference;
}
void open() {
boolean active =
bundle.getBundleState() == Bundle.ACTIVE;
if ( active )
bundle.stop(Bundle.STOP_TRANSIENTLY);
reg = context.registerService(
new String[] {
FindHook.class.getName(),
EventListenerHook.class.getName() }, this, null);
if ( active )
bundle.start(Bundle.START_TRANSIENTLY);
}
The Hide class registers a Event Listener Hook and Find Hook service in the open method. Once reg-
istered, these services will receive their event callbacks. In the find hook, the target Service Refer-
ence is removed from the results if the bundle that called the getServiceReference(s) method is the
target bundle.
The event method is the opposite of the find method. In this method, the target bundle is removed
from the event destinations if the related Service Reference is the target Service Reference.
Once the Hide class is working, a proxy can be registered. For example:
These objects provide the identity of the bundle that added a Service Listener and the optional filter
string. The Listener Hook can use this filter string to look for specific properties, for example the ob-
jectClass property to determine the type that is being sought. Extracting the property from this fil-
ter string is non-trivial though regular expressions can in general be used to extract the needed in-
formation.
The following class uses an unexplained Track object to do the low level details. The example only
shows how the Listener Hook can interact with these track objects.
The constructor saves the Bundle Context. The registration is done in an open method.
The Listener Hook has added and removed methods that take collections. It is easier to handle the
concurrency per object.
In the add hook, a ListenerInfo object provides the information about the Service Listener. In this
example, a Track object is created for each active listener and associated with the given info object.
This requires proper synchronization and should handle the rare case that the events are delivered
out of order. The ListenerInfo object contains an isRemoved method that provides this information.
If it is true, the corresponding removed event has already been called or will be called very soon. In
that case, it is safe to discard the added event. For proper cleanup, the reg field is tested to see if it is
set, if not, this call is during closing and should be ignored.
To remove a Track object it is necessary to consult the tracked map. If the track object is in the map,
it must be closed. If not, there is an out of order delivery and this event can be ignored, the add
method will ignore the corresponding ListenerInfo object because the isRemoved flag will be set. For
proper closing, the reg field is tested for null.
if ( reg == null )
return;
Track t = tracked.remove(info);
if ( t != null )
t.close();
}
The close method is straightforward. The hook services are unregistered and all the remaining Track
objects are closed. The reg field is used to make sure the event methods are ignoring any outstand-
ing calls by setting it to null. After the synchronized block, any incoming event is ignored.
Target Bundle A
a Service
Target Bundle B
Event Listener
Framework Handler
Hook
event throttle
An Event Listener Hook receives all events, REGISTERED, MODIFIED, UNREGISTERING, and
MODIFIED_ENDMATCH, that are to be delivered to all Service Listener objects registered with the
framework, regardless of the presence of a service listener filter.
The EventListenerHook class has a single method:
• event(ServiceEvent,Map) - A service event has been generated. The implementer of this method
can optionally shrink the given map of target bundles to service listeners.
One of the parameters of the event method is a map of target bundles to a collection of ListenerIn-
fo objects. The handler can shrink this map by removing bundles as well as specific service listen-
ers from the collection of ListenerHook.ListenerInfo objects. Both the map and the collection must
therefore implement the appropriate remove methods.
Removing a bundle from the list of target bundles will effectively hide the service event from the
target bundle. The target bundle can still get the service, though the Find Hook can be used to block
this access to the service.
Implementers of the Event Listener Hook must ensure that target bundles continue to see a consis-
tent set of service events. Service events are normally used in a state machine. Such state machines
can get confused if some events are missed. For example, if a Service Tracker sees a REGISTERED
event but is hidden from the corresponding UNREGISTERING event then the service will never be re-
leased. A simple solution is to stop the target bundle when the filter is put in place. However, when
the bundle that implements the Event Listener Hook is stopped, it will of course no longer be able to
filter events and the target bundle might see an service events for services it was not aware of.
The purpose of the Find Hook is to limit the visibility of services to selected target bundles. For this
reason, the hook implementation can remove selected service references from the result collection.
find hooks called. Unlike other BundleContext objects, if the system bundle's BundleContext is used
to find services then the Framework ignores the service reference removals performed by the service
Find Hooks and allows the service references removed to remain visible in the find results.
Target Bundle
a Service
Listener Hook
Framework Handler
• added(Collection) - Inform the hook of the registered listeners. The collection is immutable and
contains ListenerInfo objects. These objects identify a unique ServiceListener object registration
with the framework. They provide the registering bundle as well as the optional filter. The Lis-
tenerInfo class is nested class of the ListenerHook class.
• removed(Collection) -Inform the hook of listeners that have been removed because the bundle
is stopped or the bundle implementation has unregistered a listener. The ListenerInfo objects are
equal to their corresponding Info Listener object during the addition.
• getBundleContext() - The Bundle Context of the bundle that registered the service listener.
• getFilter() - The filter used in the registration.
• isRemoved() - Provides information if this Listener Info is still valid.
A ListenerInfo object is related to the registration of a ServiceListener with the Framework. The
Framework maintains only one registration for a specific, identity based, Service Listener object.
That is, registering the same object again, even with a different filter, will automatically unregister
the previous registration. This will be visible as a removed - added pair of calls.
The equality and hashCode method of a ListenerInfo object must guarantee that the hook can place
the Listener Info objects in hashed collections, such that an ListenerInfo object received in the
added method's collection parameter matches its corresponding ListenerInfo object in the removed
method's collection parameter. This is trivially met by the identity equals and hashCode methods if
the same objects are used in both methods.
The reason the Listener Hook provides methods that take collection instead of a single ListenerInfo
object is because of performance optimization. When a Listener Hook service gets registered, there
can already be a large number of Service Listeners available. Similarly, when a bundle gets stopped,
it could have registered a number of service listeners that then need to be unregistered. Being able to
provide all changes in a batch improves performance.
The framework must report each registration of a Service Listener with the Bundle Context with a
new ListenerInfo object that is unequal to any other ListenerInfo object. If the same Service Listener
object is registered multiple times, each previous registration must be removed before the listener is
added again.
The event method in a Listener Hook is called synchronously with the registration of the Service
Listener to minimize the overhead for the framework. However, this does not imply that delivery is
always ordered. There are rare cases where a removal is reported before the corresponding addition.
Handling this case is simplified by the isRemoved method. If the removed and added methods are
synchronized, then the isRemoved method can be used in the added method to detect the out of or-
der delivery. A simple strategy is to ignore removed events without corresponding added events and
ignore added events where the ListenerInfo object is already removed.
The following code shows a skeleton of how the Listener Hook methods can be implemented.
55.6.1 Filter
A key concept in the Listener Hook is the filter. When a bundle is interested in a specific set of ser-
vices, it registers a service listener with a filter. This filter is an indication of what services are inter-
esting to the target bundle. The objectclass property holds the names of the interfaces and classes.
However, just searching for this property with a regular expression is not guaranteed to return a us-
able value. The form of the sub-expressions can make the property part of an and or even negate. For
example, looking for the objectclass in the following expression gives a result that is the opposite of
what is searched.
(!(objectclass=org.osgi.service.cm.ConfigurationAdmin))
However, understanding a full filter expression is quite difficult. An acceptable strategy is to look for
the object classes in the filter string with a regular expression but evaluate the filter against any con-
clusions that are being drawn. That is, testing a Configuration Admin service against the filter in the
previous example will not match.
Realistically, many scenarios that are enabled by the Listener Hook will require the filters to have a
simple structure.
55.7.3 Ordering
The hooks are very sensitive to ordering because they modify the basic behavior of the OSGi Frame-
work. Before a hook is registered, a client bundle interacts with the framework directly. However, or-
dering in an OSGi Framework can never be relied upon from an programmer's perspective. It is bad
practice to rely on start level ordering in a program because updates and other disturbances will in-
evitably break this ordering. Start level ordering is a tool for deployers to smoothen initialization
problems, not to handle ordering dependencies.
Implementers of the hooks must therefore be intricately aware that they can be started before or af-
ter their target bundles are started.
55.8 Security
All hooks described in this specification are highly complex facilities that require great care in their
implementation to maintain the Framework invariants concerning the service registry. It is there-
fore important that in a secure system the permission to register these hooks is only given to privi-
leged bundles.
In this case, the user of the hook services is the framework. Therefore, there is never a need to pro-
vide:
• ServicePermission[..EventListenerHook,GET],
• ServicePermission[..FindHook,GET], or
• ServicePermission[..ListenerHook,GET]
55.9 org.osgi.framework.hooks.service
Framework Service Hooks Package Version 1.1.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.hooks.service; version="[1.1,2.0)"
55.9.1 Summary
• EventHook - OSGi Framework Service Event Hook Service.
• EventListenerHook - OSGi Framework Service Event Listener Hook Service.
• FindHook - OSGi Framework Service Find Hook Service.
• ListenerHook - OSGi Framework Service Listener Hook Service.
• ListenerHook.ListenerInfo - Information about a Service Listener.
Concurrency Thread-safe
55.9.4.1 public void find(BundleContext context, String name, String filter, boolean allServices,
Collection<ServiceReference<?>> references)
context The bundle context of the bundle performing the find operation.
name The class name of the services to find or null to find all services.
filter The filter criteria of the services to find or null for no filter criteria.
allServices true if the find operation is the result of a call to BundleContext.getAllServiceReferences(String,
String)
references A collection of Service References to be returned as a result of the find operation. The implemen-
tation of this method may remove service references from the collection to prevent the references
from being returned to the bundle performing the find operation. The collection supports all the op-
tional Collection operations except add and addAll. Attempting to add to the collection will result in
an UnsupportedOperationException . The collection is not synchronized.
□ Find hook method. This method is called during the service find operation (for example,
BundleContext.getServiceReferences(String, String) ). This method can filter the result of the find
operation.
55.10 References
[1] Whiteboard Pattern
https://www.osgi.org/wp-content/uploads/whiteboard1.pdf
56.1 Introduction
Bytecode weaving is a popular technique that transforms class files to provide additional function-
ality. This is a powerful technique that, when used with care, can significantly reduce the coding ef-
fort for mundane programming chores.
This specification provides a means for a handler bundle to intercept any bundle class loading calls
in the framework, transform the byte codes, and add new dynamic imports. A means for observing
the final weaving results, both before and after they take effect, is also provided.
56.1.1 Essentials
• Ordering - Allow a weaver to weave a bundle before it is loaded and used.
• Dynamic Imports - Support additional imports.
• Strategy - Support both Static and Dynamic Weaving strategies.
• No Metadata - Allow standard bundles, without any specific metadata, to be woven.
• Java API - Use the existing Java byte code transformation APIs where possible.
• Multiple - Allow for multiple weavers per bundle in a defined order.
• Observation - Allow woven class state transitions to be observed.
56.1.2 Entities
• Weaving Hook - A service registered by a bundle that wants to weave other bundles.
• Woven Class - An object representing the class to be woven.
• Woven Class Listener - A service registered by a bundle that wants to observe woven class state
transitions.
0..n 0..n
1 1
Framework
Impl
56.2 Usage
56.2.1 Tracing
For tracing purposes, a bundle can weave a trace entry and exit message around each method. This
can be done with byte code weaving by inserting a call to a service at the beginning and end of a
method. In this example, a service is created that has two methods:
• trace(Bundle) - Byte code weave the given bundle with trace entry and exit methods.
• untrace(Bundle) - Remove any weavings.
The strategy chosen here is simple. The weaver registers a Weaving Hook service so it receives all
class loads. Any such class load is checked against a set of bundles that needs tracing, any class from
a traced bundle is then woven with the trace information. If a bundle is to be traced, the set is updat-
ed and the bundle is refreshed to ensure all classes are loaded anew so the tracing code can be woven
in.
The weave method is the service method of the Weaving Hook service. It receives a WovenClass ob-
ject that provides the information about the class to be woven. In this case, the bundles field con-
tains the bundles to be woven, so this is checked first. If the to-be-loaded class is in one of the traced
bundles, the byte codes are changed to provide trace information. Otherwise the no change is made.
In general, weaving code will require new imports for the to-be-woven bundle. These imports can
be added by adding Dynamic Import Package clauses to the list received from the getDynamicIm-
ports() method. This is a list of String objects, the syntax of each string is equal to a clause in the Dy-
namicImport-Package header. See Dynamic Import Package on page 69 for the proper syntax.
The following trace method is called when a bundle must be traced. It ignores the request if the bun-
dle is already traced. Otherwise, it will add the bundle to the set of traced bundles and refresh the
bundle.
The refresh method uses the Bundle Wiring API to refresh a bundle. Refreshing a bundle will throw
away its class loader so that all used classes are reloaded when needed.
The trace method that does the final weaving is left as an exercise to the reader:
56.2.2 Isolation
The Resolver Hook Service Specification on page 381 allows bundles to be separated into various re-
gions isolated by sharing policies. The dynamic imports added in the tracing example will need to
be taken into account by the sharing policies of regions containing bundles whose classes were wo-
ven in order for the bundles to resolve. This can be accomplished using a Woven Class Listener. Us-
ing a Weaving Hook would not be appropriate since there is no guarantee that a Weaving Hook ob-
serves the final list of dynamic imports.
The region registers a Woven Class Listener service so it receives notifications of Woven Class state
transitions. The sharing policy of the region containing the bundle whose class was woven is up-
dated with the dynamic imports, if any. This action occurs while the Woven Class is in the TRANS-
FORMED state to ensure the region is prepared to accept the imports before the bundle wiring is up-
dated upon entering the DEFINED state. The region is initialized with the set of bundles compos-
ing it and a static sharing policy consisting of namespaces mapped to sets of filters indicating the al-
lowed capabilities.
The modified method is the service method of the Woven Class Listener service. It receives a Woven
Class object that provides the information about the woven class that underwent a state transition.
If the current state is TRANSFORMED, and the associated bundle is part of the region, the sharing
policy is updated with the additional dynamic imports, if any.
The region also implements ResolverHook. When the filterMatches method is called, the require-
ment is inspected to see if its matching capabilities are allowed into the region. If not, the list of can-
didates is cleared.
The toFilter method responsible for converting the requirement filters and dynamic import package
clauses into a Filter is left as an exercise to the reader.
tion and can be made available in environments prior to Java 5. The methods must all be called in
privileged blocks. See Privileged Callbacks on page 131.
The WovenClass object provides access to:
A Weaving Hook service can use the WovenClass object to decide to weave or not to weave. This de-
cision can be based on the bundle wiring, the class name, the protection domain, or the bytes. For
example, the following code checks if the class comes from a specific bundle:
if (wovenClass.getBundleWiring().getBundle().equals(mybundle))
...
If the Weaving Hook service decides to weave the class, it must calculate new bytes for the provid-
ed Woven Class, these bytes can be set with the setBytes(byte[]) method. This implies that order-
ing is relevant. Weaving Hook services that are lower in ranking (called later) will weave any of the
changes of higher ranking Weaving Hook services. Not all combinations of Weaving Hook services
will therefore work as expected.
Weaving a class can create new dependencies that are unknown to the woven class. In the trace ex-
ample, the entry and exit traces require access to the tracing subsystem, a dependency the original
class did not have. The WovenClass object allows these extra imports to be added as new dynamic
import package clauses. The current set of dynamic imports for the Woven Class is available from
the WovenClass getDynamicImports() method. This method returns a mutable list of String dur-
ing the weave method, the Weaving Hook service can add new dynamic import package clauses to
this list while the weave method is active. The syntax of the strings is defined by the DynamicIm-
port-Package header, see Dynamic Import Package on page 69. The dynamic imports must have a valid
syntax, otherwise an Illegal Argument Exception must be thrown. These dynamically added depen-
dencies are made visible through the Bundle Wiring API Specification on page 157 as new require-
ments. The getRevision method of these requirements must return the Bundle Revision of the bun-
dle that is woven; that revision will not include these synthetic requirements in the getDeclare-
dRequirements method.
Dynamic imports are the last resort for the framework to find a provider when the normal imports
fail. The woven class dynamic imports are consulted after the dynamic imports specified in the
bundle's manifest. Frameworks must append all additional dynamic imports in the given order but
are expected to filter out duplicates for performance reasons.
The management of the dynamic import is error prone and should be handled with care because dy-
namic imports use wildcards. Wildcards make the ordering of the imports important. In the patho-
logical case, a full wildcard in the beginning (for example in the manifest) will void any more specif-
ic clauses that were added by Handlers. Handlers should be as specific as possible when adding dy-
namic import clauses.
In many cases the additional imports must refer to classes that the Handler is already resolved to. In
an OSGi framework, the same package can be present multiple times. A Handler should therefore
ensure that the woven bundle gets wired to the correct bundle. One way to achieve this is to include
the bundle-version and bundle-symbolic-name synthetic attributes that are available on every ex-
ported package.
com.acme.weavesupport.core;version=1.2;bundle-version=3.2; «
bundle-symbolic-name=com.acme.weavesupport
After calling the last Weaving Hook service, the WovenClass object is made complete. The framework
must make the WovenClass object immutable when it is complete. After the Woven Class is com-
plete, the current bytes are then used to define the new class. Attempts to modify it, or any of its
properties, must throw an Exception. After completion, the getBytes() method must return a copy
of the byte array that was used to define the class.
56.3.1 Concurrency
Class loads can occur at any time and Weaving Hook services must be able to handle concurrent as
well as re-entrant calls to the weave method. The framework should not hold any locks when call-
ing the Weaving Hook services, and Weaving Hook service implementations must be thread-safe.
Furthermore Weaving Hook services may be re-entrant, and should be careful to avoid cycles when
weaving.
For example when a class is being woven, the Weaving Hook may implicitly load a class by having
a reference to it or the Weaving Hook can explicitly load a class. This new class load will also pass
through the Weaving Hook service, so care must be taken to avoid infinite looping.
TRANSFORMED
failure
DEFINE_FAILED
class defined
DEFINED
Woven Class Listeners are not notified of the TRANSFORMING state because the Woven Class is mu-
table and listeners are not permitted to mutate the Woven Class. For all states observed by Woven
Class Listeners, the Woven Class is effectively immutable. The first notification received for a giv-
en Woven Class is either the TRANSFORMED or TRANSFORMING_FAILED state. The TRANSFORMED
state occurs after all Weaving Hooks have been notified but before the class has been defined or the
bundle wiring has been updated for any additional dynamic imports. The TRANSFORMING_FAILED
state occurs if any Weaving Hook throws an exception. After the TRANSFORMED state, a Woven
Class can transition to either the DEFINED state or the DEFINE_FAILED state. The DEFINED state oc-
curs when the class was defined successfully and after the bundle wiring has been updated. The
DEFINE_FAILED state occurs if a class definition error occurred.
Table 56.1 describes the states of a Woven Class in more detail.
State Description
TRANSFORMING A bundle class load request was made.
• Weaving is incomplete.
• The class is undefined.
• The Woven Class is mutable.
• Weaving Hooks are notified but Woven Class Listeners are
not.
TRANSFORMED All Weaving Hooks have been notified.
• Weaving is complete.
• The class is undefined.
• The Woven Class is effectively immutable.
• Woven Class Listeners are notified.
TRANSFORMING_FAILED A Weaving Hook threw an exception.
• Weaving is incomplete.
• The class is undefined.
• The Woven Class is effectively immutable.
• Woven Class Listeners are notified.
State Description
DEFINED All Woven Class Listeners have been notified. The class has been
defined.
• Weaving is complete.
• The class is defined.
• The Woven Class is effectively immutable.
• Woven Class Listeners are notified.
DEFINE_FAILED All Weaving Hooks have been notified. A class definition failure
occurred.
• Weaving is complete.
• The class is undefined.
• The Woven Class is effectively immutable.
• Woven Class Listeners are notified.
56.4.1 Concurrency
Class loads can occur at any time, and Woven Class Listeners must be able to handle concurrent
calls to the modified method. The framework should not hold any locks when calling Woven Class
Listeners, and Woven Class Listener implementations must be thread-safe. Woven Class Listeners
must be synchronously called by the framework when a Woven Class completes a state transition.
The woven class processing will not proceed until all Woven Class Listeners are done.
56.5 Security
56.5.1 Weaving Hooks
All hooks described in this specification are highly complex facilities that require great care in their
implementation to maintain the Framework invariants. It is therefore important that in a secure
system the permission to register these hooks is only given to privileged bundles.
In this case, the user of the hook services is the framework. Therefore, there is never a need to pro-
vide:
• ServicePermission[..WeavingHook,GET]
In addition, a Weaving Hook must have Admin Permission with the WEAVE action to be able to use
the methods on the WovenClass object that mutate the state like setBytes(byte[]), getBytes(), and
the mutating methods on the list returned by getDynamicImports(). Moreover, a Weaving Hook
must have Package Permission with the IMPORT action in order to add or replace dynamic imports.
ing package import permission. The permission check for the weaver must occur during any call to
the list that results in the addition or setting of a dynamic import. If the check fails, a SecurityExcep-
tion must be thrown. If it succeeds, the implied permission must be granted to the woven bundle
immediately before defining the class.
56.6 org.osgi.framework.hooks.weaving
Framework Weaving Hooks Package Version 1.1.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.hooks.weaving; version="[1.1,2.0)"
56.6.1 Summary
• WeavingException - A weaving exception used to indicate that the class load should be failed
but the weaving hook must not be blacklisted by the framework.
• WeavingHook - OSGi Framework Weaving Hook Service.
• WovenClass - A class being woven.
• WovenClassListener - Woven Class Listener Service.
When a class is being loaded, the framework will create a WovenClass object for the class and pass
it to each registered weaving hook service for possible modification. The first weaving hook called
will see the original class file bytes. Subsequently called weaving hooks will see the class file bytes
as modified by previously called weaving hooks.
Concurrency Thread-safe
If the Java runtime environment supports permissions, any modification to the returned list
requires AdminPermission[bundle,WEAVE]. Additionally, any add or set modification requires
PackagePermission[package,IMPORT].
Returns A list containing zero or more dynamic import package descriptions to add to the bundle wiring for
this woven class. This list must throw IllegalArgumentException if a malformed dynamic import
package description is added.
See Also Core Specification, Dynamic Import Package, for the syntax of a dynamic import package de-
scription.
Receiving a woven class in the TRANSFORMED state allows listeners to observe the modified byte
codes before the class has been DEFINED as well as the additional dynamic imports before the bun-
dle wiring has been updated.
Woven class listeners are synchronously called when a woven class completes a state transition. The
woven class processing will not proceed until all woven class listeners are done.
If the Java runtime environment supports permissions, the caller must have
ServicePermission[WovenClassListener,REGISTER] in order to register a listener.
Since 1.1
Concurrency Thread-safe
56.7 References
[1] Whiteboard Pattern
https://www.osgi.org/wp-content/uploads/whiteboard1.pdf
57.1 Introduction
The OSGi API is rich and introspective supporting the local management of bundles, services and
other items. Since the API has a lot of behavior and is not designed for serialization, any manage-
ment model must design its own representation of the relevant OSGi objects for communication
with remote management systems. We see this in the Management Model Specification for JMX™
Technology, the Dmt Admin Service Specification and Residential Device Management Tree Speci-
fication: the Management Model Specification for JMX™ Technology must define the MBeans and
the Residential Device Management Tree Specification must define the tree representation.
The OSGi API continues to evolve and at each update of the OSGi API, the management models will
all need to update their representations of the OSGi objects. Having standard, simple, easy to serial-
ize and deserialize objects which represent the relevant OSGi objects will make it easier for the man-
agement model to keep up with changes in the OSGi API. Therefore, this specification defines Data
Transfer Objects for OSGi in general and well as specific Data Transfer Objects for the Core specifica-
tion. Other OSGi specifications may be updated over time to define Data Transfer Objects specific to
their domain.
57.1.1 Essentials
• Easy Serialization/Deserialization - Must be easily serializable. That is, no special serialization/dese-
rialization logic must be required. Serialization must be possible simply by introspection and ob-
ject graphs must be a tree.
• No Behavior - Must have no behavior. That is, no methods other than the default public construc-
tor.
• Public - Must have only public fields. That is, no private implementation detail.
• Limited Field Types - Must only use a limited selection of field types.
• Extendable - May extend other Data Transfer Object types.
• Snapshot - Does not track changes to represented runtime object.
• Not Thread Safe - External synchronization is needed.
• Instantiation - A means is provided to create Data Transfer Objects for the runtime objects they
represent.
57.1.2 Entities
• Data Transfer Object (DTO) - An object for carrying data between processes. A Data Transfer Ob-
ject does not have any behavior. See [1] Data Transfer Object.
• Runtime Object - A runtime object being represented by a Data Transfer Object. The runtime ob-
ject can have complex behavior.
• Primitive types
• Wrapper classes for the primitive types
• String
• enum
• Version
• Data Transfer Objects
• List
• Set
• Map
• array
The List, Set, Map and array aggregates must only hold objects of the listed types.
Data Transfer Objects are public classes with no methods, other than the compiler supplied default
constructor, having only public fields limited to the easily serializable types mentioned above. The
org.osgi.dto package defines the basic rules and the abstract base DTO class which Data Transfer Ob-
jects must extend.
A Data Transfer Object is a representation of a runtime object at the point in time the Data Transfer
Object was created. Data Transfer Objects do not track state changes in the represented runtime ob-
ject. Since Data Transfer Objects are simply fields with no method behavior, modifications to Data
Transfer Object are inherently not thread safe. Care must be taken to safely publish Data Transfer
Objects for use by other threads as well as proper synchronization if a Data Transfer Object is mutat-
ed by one of the threads.
The object graph from a Data Transfer Object must be a tree to simplify serialization and deserializa-
tion.
requirer for
<<dto>>
declares 0..n 1 requirer for
Requirement
DTO
0..n
1 1
<<dto>> <<dto>> provided 0..n <<dto>>
1
Resource DTO Wiring DTO 0..n Wire DTO
required
1 1
0..n
<<dto>>
Capability DTO 1 provider for
declares 0..n
provider for
<<dto>> 1
1 Bundle Revision 1
DTO
1 1 1..n
0..n 1 0..n
<<dto>> <<dto>> <<dto>> <<dto>>
Requirement DTO Bundle Wiring 1 Bundle DTO Capability DTO
DTO
1 1
root
1..n 1
<<dto>>
1 Bundle Wiring 1
DTO.Node DTO
requirer requirer provider provider
<<dto>>
Wiring DTO
0..n 0..n
<<dto>>
Bundle Wire
DTO
<<dto>>
Wire DTO
The following table shows the Core Data Transfer Objects that can be obtained via the adapt
method.
Table 57.1 Data Transfer Objects that can be adapted from Bundle
Class Description
BundleDTO The Bundle Data Transfer Object for the bundle.
ServiceReferenceDTO [] An array of Service Reference Data Transfer Objects for the regis-
tered services of the bundle. If the bundle has no registered ser-
vices, the result is an empty array. If the bundle does not have a
valid bundle context, the result is null.
BundleRevisionDTO The Bundle Revision Data Transfer Object for the bundle. If the
bundle is uninstalled or otherwise does not have a bundle revi-
sion, the result is null.
BundleRevisionDTO [] The Bundle Revision Data Transfer Objects for the bundle. The
first revision is the current revision. If the bundle is uninstalled,
the result is null.
BundleWiringDTO The Bundle Wiring Data Transfer Object for the bundle. If the
bundle is unresolved or otherwise does not have a bundle wiring,
the result is null.
BundleWiringDTO[] The Bundle Wiring Data Transfer Objects for the bundle. The first
wiring is the current wiring. If the bundle is uninstalled, the re-
sult is null.
BundleStartLevelDTO The Bundle Start Level Data Transfer Object for the bundle. If the
bundle is uninstalled, the result is null.
FrameworkStartLevelDTO The Framework Start Level Data Transfer Object if the bundle is
the System Bundle. If the bundle is not the System Bundle, the re-
sult is null.
FrameworkDTO The Framework Data Transfer Object if the bundle is the System
Bundle. If the bundle is not the System Bundle, the result is null.
FrameworkWiringDTO The Framework Wiring Data Transfer Object if the bundle is the
System Bundle. If the bundle is not the System Bundle, the result
is null.
57.5 Security
Data Transfer Objects have no behavior by definition and thus no permissions are applica-
ble to their use. To obtain Data Transfer Objects from a Bundle object via the adapt method,
AdaptPermission[<dtotype>,ADAPT] is required for the desired Data Transfer Object type.
57.6 org.osgi.dto
57.6.1 Summary
• DTO - Super type for Data Transfer Objects.
57.7 org.osgi.framework.dto
OSGi Data Transfer Object Framework Package Version 1.8.
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 pack-
age and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.dto; version="[1.8,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.framework.dto; version="[1.8,1.9)"
57.7.1 Summary
• BundleDTO - Data Transfer Object for a Bundle.
• FrameworkDTO - Data Transfer Object for a Framework.
• ServiceReferenceDTO - Data Transfer Object for a ServiceReference.
57.8 org.osgi.framework.startlevel.dto
OSGi Data Transfer Object Framework Start Level Package Version 1.0.
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 pack-
age and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.startlevel.dto; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.framework.startlevel.dto; version="[1.0,1.1)"
57.8.1 Summary
• BundleStartLevelDTO - Data Transfer Object for a BundleStartLevel.
57.9 org.osgi.framework.wiring.dto
57.9.1 Summary
• BundleRevisionDTO - Data Transfer Object for a BundleRevision.
• BundleWireDTO - Data Transfer Object for a BundleWire.
• BundleWiringDTO - Data Transfer Object for a BundleWiring graph.
• BundleWiringDTO.NodeDTO - Data Transfer Object for a BundleWiring node.
• FrameworkWiringDTO - Data Transfer Object for the wiring graph of the framework.
57.10 org.osgi.resource.dto
OSGi Data Transfer Object Resource Package Version 1.0.
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 pack-
age and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.resource.dto; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.resource.dto; version="[1.0,1.1)"
57.10.1 Summary
• CapabilityDTO - Data Transfer Object for a Capability.
• CapabilityRefDTO - Data Transfer Object for a reference to a Capability.
• RequirementDTO - Data Transfer Object for a Requirement.
57.11 References
[1] Data Transfer Object
https://en.wikipedia.org/wiki/Data_transfer_object
57.12 Changes
• Added support for enums and Version fields in DTOs.
• A new DTO for the complete framework wiring, FrameworkWiringDTO, is added.
58.1 Introduction
Today very few applications are self contained, the predominant development model is that appli-
cations are built from (external) components, which are often open source. Application developers
add business logic, glue code, and assemble the diverse components into a resource that provides
the desired capabilities when installed in an environment. Designing the assembly has long been a
manual and error prone process, partly due to the complexity of external dependencies. Although
the direct dependencies are often given, the largest number of dependencies are usually the tran-
sitive dependencies: the dependencies of the dependencies. Modern applications can end up with
hundreds to thousands of external dependencies. Numbers that make tooling inevitable.
The OSGi framework is the first specification that provides a foundation for automating a signifi-
cant part of this assembly process. The Requirement-Capability model defined in Resource API Spec-
ification on page 151 provides a dependency model that allows resources to express dependencies,
constraints, and capabilities. If a resource's constraints are met it provides capabilities that can satis-
fy further requirements. The OSGi dependency model is fully generic and is not limited to bundles.
Resources can be bundles but also certificates, plugged in devices, etc.
Resolving transitive dependencies is a non-trivial process that requires careful design to achieve the
required performance since the underlying problem is NP-complete. OSGi frameworks have always
included such resolvers but these were built into the frameworks. They were not usable outside the
framework for tooling, for example automatically finding the dependencies of a bundle that needs
to be installed.
The number of dependencies is rapidly reaching a threshold where manual methods no longer can
provide reliable results. This specification therefore provides the Resolver service, a service that can
be the base for provisioning, deployment, build, and diagnostic tooling. The service can take a re-
quirement and resolve it to a wiring of resources. For example, with cloud computing a new re-
quirement can be translated into a new OSGi framework instance being started on a node and pro-
visioned with the set of bundles that satisfy the given requirement. The OSGi Resolver service is in-
tended be a corner stone of such an auto-provisioning tool.
However, the OSGi Resolver service is not limited to these higher end schemes. Build tools can use
the Resolver to find components for the build path and/or run time environment and predict the re-
sults of installing a set of bundles on a target environment. The OSGi Resolver service is an essential
part of a software model where applications are built out of independent components.
This specification is based on the concepts and API defined in the Resource API Specification on page
151, Bundle Wiring API Specification on page 157, and the Module Layer on page 33. These specifica-
tions are required reading for understanding this specification. This specification is for highly spe-
cialized use, it is not intended to be used in applications, the Resolver API is a low level service in-
tended for system developers with deep knowledge of the OSGi module layer.
58.1.1 Essentials
• Transitive - From a requirement, find a consistent set of resources that satisfy that requirement.
• Diagnostics - Provide diagnostic information when no resolution can be found.
58.1.2 Entities
• Environment - A container or framework that can install resources and uses a Resolver to wire
these resources.
• Resolve Context - An interface implemented by the management agent to provide the context of
the resolution.
• Wiring - Represents the state of a resource's wires, requirements, and capabilities in an environ-
ment.
• Resolver - A service that can find a set of wires that can be applied to an existing wiring state
where a set of initial resources have all their mandatory requirements satisfied.
• Wire - Links requirement to a capability.
• Resource -An artifact with requirements that need to be provisioned and resolved to provide its
capabilities.
• Requirement - A necessity for a given resource before it can provide its capabilities; expressed as a
filter expression on the attributes of a capability in a given namespace.
• Capability - A set of attributes and directives defined by a namespace, describes what a resource
provides when resolved.
• Hosted Capability - Pairs a resource with a capability to model hosting capabilities in another re-
source.
• Namespace - The type for a capability and requirement.
• Resolution - The result of a resolve operation.
<<interface>>
Capability
1
Resolver Impl <<interface>>
Hosted
Capability
58.1.3 Synopsis
The Resolver service can find a complete and consistent set of transitive dependencies starting with
an initial set of mandatory and optional resources. Such a set can be used to install resources in the
environment from local or remote repositories. To use the Resolver service, the client must provide
a ResolveContext object. This complex object represents the context of a resolution; it provides the
initial resources (optional and mandatory), defines a number of namespaces specific policies, and
provides the state of the environment.
A resolution can be based on an existing wiring in the environment, for example the current frame-
work state. For the framework, the Resolve Context can find this existing state via the Bundle Wiring
API Specification on page 157. The Resolver must then satisfy all the requirements of the mandatory
resources. The Resolver must always ask the Resolve Context to find additional capabilities for the
unsatisfied requirements. A capability is always associated with a resource, which is subsequently
associated with additional requirements. The final resolution must contain a set of resources that
include the initial set of mandatory resources, has no unsatisfied mandatory requirements, and is
consistent with the implied constraints. Otherwise it fails.
The Requirement-Capability model is fully generic but provides special semantics through the use
of namespaces. The Resolver must implement the standard OSGi namespaces as described in Bun-
dle Wiring API Specification on page 157, which includes the uses constraints. Part of the semantics
of the OSGi namespaces are delegated to the Resolve Context so that it can implement different poli-
cies. Singletons, ordering of capabilities, and matching are the responsibility of the Resolve Context;
the Resolver never matches a requirement to a capability.
Requirements have an effective directive that indicates in what situations the requirement must be
resolved. Also here, the Resolve Context decides if a particular requirement is effective or not. Only
effective requirements are wired in the resolution.
Since capabilities are declared by resources that have additional requirements, the Resolver must
create a set of resources where all transitive requirements are satisfied or fail with a Resolution Ex-
ception. This Resolution Exception can provide additional details why the resolution failed, if possi-
ble.
At the end of a successful resolve operation the Resolver returns a Map<Resource,List<Wire>>. These
wires are a delta on the existing state, if any. The wires can then be used to provision missing re-
sources or to provide diagnostic feedback.
The Resolver service separates these two stages and thus allows a third party, the management agent, to
define the environment of the resolution. A management agent can interact with the Resolver service
while it is searching for a resolution because the Resolver service calls back the management agent
through a ResolveContext object. The Resolver service will therefore allow the management agent
to handle more scenarios, better diagnostics, etc.
The Resolve Context is provided by the management agent, it is an abstract base class and must
therefore be extended. It is a non-trivial class to implement since it is tightly coupled to the rules of
the environment; it represents the policies of the management agent for that environment. For OS-
Gi framework resolvers, the Resolve Context must understand and implement a part of the OSGi
framework namespaces.
With the Resolver service, a management agent can try out resolutions before any bundle can see
the result of such a resolution but it can also include extra bundles or other resources on demand.
The Resolver service will also allow resolutions to be calculated for other frameworks.
For example, a management agent could use a Resolver service to find missing dependencies and in-
stall them on demand from a local directory with bundles. Such a Provisioner could have the follow-
ing skeleton:
try {
ResolveContextImpl rc = ...
rc.addMandatory( resource );
Set<Resource> provision = resolver.resolve( rc ).keySet();
The Resolver can, and likely will, use the returned list to maintain its internal state during
the resolve operation while trying out different potential solutions. It can add and remove
capabilities at will. The returned list must therefore be mutable and not reused, after it is re-
turned; it becomes owned by the Resolver. However, the Resolver can call back later with the
insertHostedCapability(List,HostedCapability) method, giving back the returned list as the first pa-
rameter, see Insert Hosted Capabilities on page 454.
For example, assume that all possible resources in the previous example can be gotten with the
getSortedResources method in the preferred resource order. This list contains all installed re-
sources as well as any potentially installable resources. This list is sorted once on the given ordering
criteria, this only has to be done once and not for each findProviders(Requirement) method invoca-
tion. The following code, which does not order by capability versions, could then be a simple skele-
ton for the findProviders(Requirement) method on the ResolveContextImpl inner class:
return result;
}
58.2.3 Matching
The findProviders(Requirement) method is responsible for only returning the capabilities that the
management agent wants to be considered by the Resolver. Since the Resolver must never match
any requirements to capabilities it allows the management agent to fully control the matching.
However, in an OSGi environment the following matching behavior is expected:
The following example shows a skeleton match method that provides OSGi semantics:
if ( !c.getNamespace().startsWith( "osgi.wiring." ) )
return true;
List<String> attrs =
Arrays.asList( mandatory.toLowerCase().split( "\\s*,\\s*") );
return mandatory.isEmpty();
}
58.2.4 Repositories
Resolving to provision a framework is different than a framework resolving itself. During provision-
ing remote repositories can be consulted to find external resources while the framework only re-
solves a limited set (the installed bundles). These repositories generally contain magnitudes more
bundles than what is installed in a framework.
Repositories do not implement any namespace specific semantics and therefore do not understand
any directives. Repositories only verify the requirement's filter (if any) against the capability's attrib-
utes. The Resolver expects the Resolve Context to do the namespace specific matching. The [1] Repos-
itory Service Specification provides the details for a service that abstracts a Requirement-Capability
aware repository.
With such a repository service the findProviders(Requirement) method can be implemented as fol-
lows:
A wiring for a resource may also have a subset of required wires which substitute capabilities pro-
vided by the resource or one of its attached fragment resources. The getSubstitutionWires(Wiring)
method is called by the resolver in order to find the wires that substitute capabilities of the wiring.
For example, when a wiring provides a osgi.wiring.bundle capability that is used to resolve one or
more osgi.wiring.bundle requirements. In this case the resolver needs to discover which capabilities
have been substituted in order to ensure a consistent class space (see Requiring Bundles on page 84).
In order to get the capabilities which have been substituted, the resolver asks the resolve context to
return the substitution wires for the wiring.
Note that the default implementation of this method searches all the osgi.wiring.package capabil-
ities which are declared as provided by the resource associated with the wiring and fragment re-
sources wired to the wiring with the osgi.wiring.host namespace. The provided capabilities are com-
pared against the required package wires to determine which wires are substitution wires. Subclass-
es of ResolveContext should provide a more efficient implementation of this method.
58.2.6 Effective
The Resolver service is designed to work with OSGi frameworks but the scope is broader; its de-
sign allows many alternative usages. The effective directive on the capabilities and requirements
is meant to allow requirements and capabilities to be effective in different phases. The default is re-
solve, the value for an OSGi framework resolving process. Bundles and other OSGi defined artifacts
must declare their capabilities and requirements in the resolve effective time to be considered by an
OSGi resolver.
However, Resolvers can use the effective directive to run the Resolver at other times than the stan-
dard OSGi framework resolve. For example, it could be possible to define an active time to resolve the
service dependencies.
For this reason, the Resolver is designed to be agnostic for this directive, it will always ask the Re-
solveContext if a requirement is effective. It does this with the isEffective(Requirement) method.
Since the Resolver service never matches requirements to capabilities it is also up to the Resolve
Context to decide how to treat the effective directive. For an OSGi resolve operation, capabilities
should also have an effective time value of resolve (or not set since resolve is the default).
To make requirements effective during the resolving of bundles it will be necessary to implement
the isEffective(Requirement) method similar to:
Capabilities the Resolver needs a way to add them to the lists of capabilities returned from
findProviders(Requirement). The Resolver service cannot add them itself since this list has a prefer-
ence order, the Resolver service must therefore ask the Resolve Context to insert this new capability
to allow the Resolve Context to maintain the desired order.
The Resolve Context must therefore implement an insertHostedCapability(List,HostedCapability)
method. The given list must have been returned earlier from a findProviders(Requirement) method
invocation. The Resolve Context must find the appropriate position to insert the HostedCapability
object, insert it, and return the index of the inserted object.
It is the responsibility of the Resolve Context to find the proper position. In Finding Capabilities on
page 451 it was discussed how the findProviders(Requirement) method must return an ordered
list. The insertHostedCapability(List,HostedCapability) has that same responsibility.
The following example shows how the Hosted Capability is inserted based on the index of the host-
ed resource's index in the sorted list of resources the management agent maintained. The example
iterates through the capabilities and compares the index of sorted resources to indicate preference.
If it finds a capability from a resource that was later in the list of sorted resources then it inserts it at
that position. A real implementation should also take the version of the capability into account.
58.2.8 Fragments
Fragments are resources that have an osgi.wiring.host requirement that must match a capability
from one or more host bundles. However, for example an Export-Package in a fragment must be
merged with its attached hosts. These capabilities and requirements from namespaces that appear
as if they come from the host bundle are called hosted.
When resolving a set of resources it must be possible to pull in any available fragments which may
attach to the resource. Since fragments are not required by the host bundle, there will be no resource
requiring the fragment bundles. However, fragments will require their hosts. A Resolver should at-
tach any fragments available in a resolution to suitable hosts.
In order to discover additional fragments which may be attached to the resources in a resolution the
findRelatedResources(Resource) method is called by the resolver . The resolver attempts to also re-
solve the related resources during the current resolve operation. Failing to resolve one of the related
resources must not result in a resolution exception unless the related resource is also considered a
mandatory resource.
A resolve context may consider a fragment to be a related resource for the hosts it can attach to. In
order for the resolver to pull the fragments into the resolve operation the resolve context is asked
to return the related resources of each host bundle which is to be resolved. The resolve context may
decide if the fragments of the host needs to be resolved along with the host. Note that fragments are
used as an example of a related resource. The resolve context is free to use any type of resource as a
related resource.
Fragments can of course also be found by the normal finding of capabilities.
This constraint is not enforced by the Resolver service to give more flexibility to management
agents. The Resolve Context must ensure that it does not return capabilities from conflicting single-
ton resources from the findProviders(Requirement) method. When the Resolver is used with a lim-
ited set of resources then it is possible to enumerate all singletons ahead of time and use permuta-
tions. However, when repositories are used an incremental method works better because the scope
is so much larger.
When the findProviders(Requirement) method is called for a requirement that selects a capability
declared in a singleton then it is likely that repositories will return multiple versions of this single-
ton including the resource with the highest available version for conflicting resources. It is there-
fore possible to maintain a white list of singletons incrementally.
Once the findProviders(Requirement) method has created a result list, it is possible to prune this list
of conflicting singletons. This can be an incremental process, the first time a singleton is encoun-
tered in such a list of capabilities the highest version can be selected as the singleton. Other single-
tons that are in that list or come in other invocations of findProviders(Requirement) can then no
longer provide capabilities. For example:
this.whitelist.putAll( singletons );
58.2.10 Diagnostics
The Resolver service throws a ResolutionException when the resolve operation cannot find a so-
lution. This Exception provides the standard human readable message. However, there is also the
getUnresolvedRequirements() method. With this method it is possible to find what requirements
could not be matched. Though this is very useful in many cases it must be realized that resolving is
a complicated process. It is not possible to establish the exact set of missing requirements because
any unresolved resolution can have many, different, sets of unresolved requirements. This is an in-
trinsic part of the resolution problem. There is also no guarantee that providing capabilities that sat-
isfy these requirements will give a successful resolution. There could still be other constraints that
cannot be satisfied. In general, the Resolve Context can already detect any unresolved mandatory re-
quirements when it cannot find a matching capability in the findProviders(Requirement) method.
That said, the getUnresolvedRequirements() can often point to a potential solution.
58.2.11 Cancel
Some resolution operations can be long running, and therefore a resolve context may want to
cancel the currently running resolve operation. The resolver must register a single runnable call-
back with the resolve context that is associated with the currently running resolve operation. The
onCancel(Runnable) method must be invoked by the resolver implementation before any other
method on the resolve context is invoked. The resolve context invokes the callback to cancel the
currently running resolve operation that appears to be running endlessly or at risk of running out
of resources. The resolve context may give up on the resolve operation or attempt to try another re-
solve operation with a smaller set of resources which may allow the resolve operation to complete
normally.
58.2.12 Complexity
Implementing a Resolve Context is a non-trivial task that requires extensive knowledge of the OS-
Gi framework, especially the module layer. Though this section contains numerous code examples,
they are not sufficient to implement a real Resolve Context since this would require too much code
for a specification.
58.3.1 Variables
The resolve(ResolveContext) method uses a Resolve Context to provide the context and parameters
of the resolution. During the resolution process the Resolver service can callback the Resolve Con-
text to retrieve the following information:
Rm Collection<Resource> getMandatoryResources()
Ro Collection<Resource> getOptionalResources()
Cenv Map<Requirement,List<Capability>> Combined answers from the
findProviders(Requirement) method
Qeff Collection<Requirement> Set of effective requirements as defined by the
isEffective(Requirement) method
X Map<Resource,Wiring> An existing Wiring state, getWirings()
S Map<Wiring,List<Wire>> The substitution wires of an existing Wiring
state, getSubstitutionWires(Wiring)
The Resolver service returns the following:
D Map<Resource,List<Wire>> The resolution, a delta on the existing state
The resolve(ResolveContext) method returns a resolution D that is a delta on the existing Wiring
state X. It is up to the Resolve Context to ensure that the delta D is installed. In for example the OSGi
framework the framework hooks can be used to guide the framework's resolving process.
58.3.2 Resolving
The goal of the Resolver is to provide a set of wires between a set of resolved resources. A resource is
resolved when all its mandatory and effective requirements are satisfied by capabilities from resolved
resources. A Resolver must not return wires between resources that have unsatisfied mandatory re-
quirements.
A mandatory requirement has a resolution directive that is not set or that is set to mandatory. The
effectiveness of a requirement is defined by the Resolve Context, a Resolver service must call the
isEffective(Requirement) method to establish if a requirement is effective for a given resolve opera-
tion. A Resolver must never create a wire from a requirement that is not effective.
To find a resolution, the Resolver must use the Resolve Context to find candidate capabilities for the
requirements declared in the resources that it needs to resolve. A candidate capability is a capabili-
ty that satisfies the requirement. From the perspective of the Resolver service, a requirement is satis-
fied by a capability when that capability is returned from the findProviders(Requirement) method.
A Resolver has no alternative way to find out if a requirement is satisfied by a capability and must
therefore not make any assumptions about matching. Any matching rules like for example the
osgi.wiring.* mandatory directive must be implemented by the Resolve Context. A Resolve Context
must always return the same capabilities during a resolving operation when given the same require-
ment.
Since the resolver cannot match requirements and capabilities the Resolve Context must return ca-
pabilities for all possible resources, this must include:
It can include additional resources that were indirectly returned through the
findProviders(Requirement) method.
The existing wiring X and its substitution wires S provides an existing set of constraints
that the Resolver service must abide by. It can get this state with the getWirings() and
getSubstitutionWires(Wiring) methods. The purpose of the existing state is to ensure that any wires
are compatible with existing wiring. For an OSGi framework it is crucial that the uses constraints
are maintained for the resolution, see Module Layer on page 33.
The Resolver service can wire new requirements to existing capabilities but it can never create wires
for an existing requirement from the existing wiring unless the resolve process is for a dynamic re-
solve, see Dynamic Resolving on page 459.
If the Resolver service attaches a hosted resource like a fragment, and thereby needs to add new
HostedCapability objects to a previously returned list from findProviders(Requirement) then it
must call the Resolve Context's insertHostedCapability(List,HostedCapability) method.
Fragments can be attached to resolved resources or to resources that declare the capabilities re-
turned from findProviders(Requirement), that is, Cenv. Additional resources are also pulled into the
resolve operation by invoking the findRelatedResources(Resource) method on the resolve context.
As part of the related resources the resolve context can include fragments to be considered as part of
the resolve operation. This allows the available fragments to be resolved when the host is being re-
solved.
This specification does not define the detailed rules and constraints associated with resolving; these
rules are defined in their namespaces. An OSGi Resolver service must support at least all name-
spaces defined in Framework Namespaces Specification on page 171 except for the following directives:
A Resolver service must support the uses constraints and any applicable rule defined in the Module
Layer on page 33 for the osgi.wiring.* namespaces.
The Resolver must return a delta wiring to the existing state (potentially empty) or throw an Excep-
tion. The resolution:
The Resolver assumes the following about the host wiring and the dynamic requirement:
The Resolver is not required to validate these assumptions. If these assumptions are not true then
the result of the dynamic resolution is not specified.
The Resolver uses the dynamic requirement to call findProviders(Requirement) in order to find
valid matching capabilities. In order for a matching capability to be considered as valid it must satis-
fy the following rules:
The Resolver assumes the matching capabilities are valid. If invalid capabilities are returned by the
Resolve Context then the result of the dynamic resolution is not specified.
At this point the dynamic resolution continues on as a normal resolution where the host wiring re-
source is considered a mandatory resource and the dynamic requirement is considered a mandato-
ry requirement. The resources providing the matching capabilities to the dynamic requirement are
then resolved as in a normal resolution operation.
58.4 Security
58.4.1 Resolving
The Resolver service is a pure function that has no state. The Resolve Context maintains the state
and is therefore the actor that requires most permissions. In general, it will require access to the
Wiring API and Repositories.
Since the Resolver requires no external access it does not have to be a trusted service. Resolve Con-
texts that support security must ensure that the callbacks are executed in a privileged block.
58.5 org.osgi.service.resolver
Resolver Service 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 pack-
age 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.resolver; version="[1.1,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.resolver; version="[1.1,1.2)"
58.5.1 Summary
• HostedCapability - A capability hosted by a resource.
• ResolutionException - Indicates failure to resolve a set of requirements.
• ResolveContext - A resolve context provides resources, options and constraints to the potential
solution of a resolve operation.
• Resolver - A resolver service resolves the specified resources in the context supplied by the
caller.
A HostedCapability is a Capability where the getResource() method returns a Resource that hosts
this Capability instead of declaring it. This is necessary for cases where the declaring Resource of a
Capability does not match the runtime state. For example, this is the case for fragments attached to
a host. Most fragment declared capabilities and requirements become hosted by the host resource.
Since a fragment can attach to multiple hosts, a single capability can actually be hosted multiple
times.
Concurrency Thread-safe
Provider Type Consumers of this API must not implement this type
Returns A collection of the unresolved requirements for this exception. The returned collection may be emp-
ty if no unresolved requirements information is available.
• Specify the mandatory and optional resources to resolve. The mandatory and optional resources
must be consistent and correct. For example, they must not violate the singleton policy of the im-
plementer.
• Provide capabilities that the Resolver can use to satisfy requirements via the
findProviders(Requirement) method
• Constrain solutions via the getWirings() method. A wiring consists of a map of existing re-
sources to wiring.
• Filter requirements that are part of a resolve operation via the isEffective(Requirement).
A resolver may call the methods on the resolve context any number of times during a resolve opera-
tion using any thread. Implementors should ensure that this class is properly thread safe.
Except for insertHostedCapability(List, HostedCapability) and onCancel(Runnable), the resolve con-
text methods must be idempotent. This means that resources must have constant capabilities and re-
quirements and the resolve context must return a consistent set of capabilities, wires and effective
requirements.
Concurrency Thread-safe
The resolver attempts to resolve related resources during the current resolve operation. Failing to
resolve one of the related resources will not result in a resolution exception unless the related re-
source is also a mandatory resource.
The resolve context is asked to return related resources for each resource that is pulled into a resolve
operation. This includes the mandatory and optional resources and each related resource returned
by this method.
For example, a fragment can be considered a related resource for a host bundle. When a host is being
resolved the resolve context will be asked if any related resources should be added to the resolve op-
eration. The resolve context may decide that the potential fragments of the host should be resolved
along with the host.
Returns A collection of the resources that the resolver should attempt to resolve for this resolve context.
May be empty if there are no related resources. The returned collection may be unmodifiable.
Since 1.1
For example, if this resolve context is for an OSGi framework, then the result would contain all the
currently resolved bundles with each bundle's current wiring.
Multiple calls to this method for this resolve context must return the same result.
Returns The wirings for existing resolved resources. The returned map is unmodifiable.
• Mandatory - any resource in the mandatory group must be resolved. A failure to satisfy any
mandatory requirement for these resources will result in throwing a ResolutionException
• Optional - any resource in the optional group may be resolved. A failure to satisfy a mandatory
requirement for a resource in this group will not fail the overall resolution but no resources or
wires will be returned for that resource.
The resolve method returns the delta between the start state defined by
ResolveContext.getWirings() and the end resolved state. That is, only new resources and wires are
included.
The behavior of the resolver is not defined if the specified resolve context supplies inconsistent in-
formation.
Returns The new resources and wires required to satisfy the specified resolve context. The returned map is
the property of the caller and can be modified by the caller.
Throws ResolutionException– If the resolution cannot be satisfied.
58.6 References
[1] Repository Service Specification
OSGi Compendium, Chapter 132 Repository Service Specification
58.7 Changes
• Added new methods: findRelatedResources, onCancel, getSubstitutionWires, and resolveDynam-
ic.
701.1 Introduction
The Framework provides a powerful and very dynamic programming environment: Bundles are in-
stalled, started, stopped, updated, and uninstalled without shutting down the Framework. Depen-
dencies between bundles are monitored by the Framework, but bundles must cooperate in handling
these dependencies correctly. Two important dynamic aspects of the Framework are the service reg-
istry and the set of installed bundles.
Bundle developers must be careful not to use service objects that have been unregistered and are
therefore stale. The dynamic nature of the Framework service registry makes it necessary to track
the service objects as they are registered and unregistered to prevent problems. It is easy to over-
look race conditions or boundary conditions that will lead to random errors. Similar problems exist
when tracking the set of installed bundles and their state.
This specification defines two utility classes, ServiceTracker and BundleTracker , that make tracking
services and bundles easier. A ServiceTracker class can be customized by implementing the Service-
TrackerCustomizer interface or by sub-classing the ServiceTracker class. Similarly, a BundleTracker
class can be customized by sub-classing or implementing the BundleTrackerCustomizer interface.
These utility classes significantly reduce the complexity of tracking services in the service registry
and the set of installed bundles.
701.1.1 Essentials
• Simplify - Make it simple to tracking services or bundles.
• Customizable - Allow a default implementation to be customized so that bundle developers can
start simply and later extend the implementation to meet their needs.
• Small - Every Framework implementation should have this utility implemented. It should there-
fore be very small because some Framework implementations target minimal OSGi frameworks.
• Services - Track a set of services, optionally filtered, or track a single service.
• Bundles - Track bundles based on their state.
• Cleanup - Properly clean up when tracking is no longer necessary
• Generified - Generics are used to promote type safety.
701.1.2 Operation
The fundamental tasks of a tracker are:
A ServiceTracker object is populated with a set of services that match given search criteria, and then
listens to ServiceEvent objects which correspond to those services. A Bundle Tracker is populated
with the set of installed bundles and then listens to BundleEvent objects to notify the customizer of
changes in the state of the bundles.
701.1.3 Entities
Figure 701.1 Class diagram of org.osgi.util.tracker
Service Service
Tracker Tracker
1 customized by 0..1 Customizer
Bundle Bundle
Tracker Tracker
1 customized by 0..1 Customizer
701.2 Tracking
The OSGi Framework is a dynamic multi-threaded environment. In such an environments callbacks
can occur on different threads at the same time. This dynamism causes many complexities. One of
the surprisingly hard aspects of this environment is to reliably track services and bundles (called tar-
gets from now on).
The complexity is caused by the fact that the BundleListener and ServiceListener interfaces are on-
ly providing access to the changed state, not to the existing state when the listener is registered. This
leaves the programmer with the problem to merge the set of existing targets with the changes to the
state as signified by the events, without unwantedly duplicating a target or missing a remove event
that would leave a target in the tracked map while it is in reality gone. These problems are caused by
the multi-threaded nature of OSGi.
The problem is illustrated with the following (quite popular) code:
case BundleEvent.UNINSTALLED:
map.remove(bundle.getLocation());
break;
default:
// ignore
}
}
});
Assume the code runs the first part, getting the existing targets. If during this time a targets state
changes, for example bundle is installed or uninstalled, then the event is missed and the map will
miss a bundle or it will contain a bundle that is already gone. An easy solution seems to be to first
register the listener and then get the existing targets. This solves the earlier problem but will be in-
troduce other problems. In this case, an uninstall event can occur before the bundle has been discov-
ered.
Proper locking can alleviate the problem but it turns out that this easily create solutions that are
very prone to deadlocks. Solving this tracking problem is surprisingly hard. For this reason, the OS-
Gi specifications contain a bundle tracker and a service tracker that are properly implemented. These
classes significantly reduce the complexity of the dynamics in an OSGi framework.
701.2.1 Usage
Trackers can be used with the following patterns:
• As-is - Each tracker can be used without further customizing. A tracker actively tracks a map of
targets and this map can be consulted with a number of methods when the information is need-
ed. This is especially useful for the Service Tracker because it provides convenience methods to
wait for services to arrive.
• Callback object - Each tracker provides a call back interface that can be implemented by the client
code.
• Sub-classing - The trackers are designed to be sub-classed. Sub-classes have access to the bundle
context and only have to override the callback methods they need.
• Adding - Provide a new object, obtained from the store or from an event and return the wrapper
or a related object. The adding method can decide not to track the target by returning a null ob-
ject. When null is returned, no modified or remove methods are further called. However, it is
possible that the adding method is called again for the same target.
• Modified - The target is modified. For example, the service properties have changed or the bundle
has changed state. This callback provides a mechanism for the client to update its internal struc-
tures. The callback provides the wrapper object.
• Removing - The target is no longer tracked. This callback is provided the wrapper object returned
from the adding method. This allows for simplified cleanup if the client maintains state about
the target.
Each tracker is associated with a callback interface, which it implements itself. That is, a Service
Tracker implements the ServiceTrackerCustomizer interface. By implementing this customizer,
the tracker can also be sub-classed, this can be quite useful in many cases. Sub-classing can over-
ride only one or two of the methods instead of having to implement all methods. When overriding
the callback methods, it must be ensured that the wrapper object is treated accordingly to the base
implementation in all methods. For example, the Service Tracker's default implementation for the
adding method checks out the service and therefore the remove method must unget this same ser-
vice. Changing the wrapper object type to something else can therefore clash with the default im-
plementations.
Trackers can provide all the objects that are tracked, return the mapped wrapper from the target,
and deliver the number of tracked targets.
• The tracker code calling a callback must not hold any locks
Clients must be aware that their callbacks are reentrant though the tracker implementations guar-
antee that the add/modified/remove methods can only called in this order for a specific target. A
tracker must not call these methods out of order.
701.2.5 Synchronous
Trackers use synchronous listeners; the callbacks are called on the same thread as that of the initi-
ating event. Care should be taken to not linger in the callback and perform non-trivial work. Call-
backs should return immediately and move substantial work to other threads.
The ServiceTracker interface defines three constructors to create ServiceTracker objects, each pro-
viding different search criteria:
Each of the ServiceTracker constructors takes a BundleContext object as a parameter. This Bundle-
Context object must be used by a ServiceTracker object to track, get, and unget services.
A new ServiceTracker object must not begin tracking services until its open method is called. There
are 2 versions of the open method:
• open() - This method is identical to open(false). It is provided for backward compatibility rea-
sons.
• open(boolean) - The tracker must start tracking the services as were specified in its constructor.
If the boolean parameter is true, it must track all services, regardless if they are compatible with
the bundle that created the Service Tracker or not. See Multiple Version Export Considerations on
page 148 for a description of the compatibility issues when multiple variations of the same pack-
age can exist. If the parameter is false, the Service Tracker must only track compatible versions.
• getService() - Returns one of the services being tracked or null if there are no active services be-
ing tracked.
• getServices() - Returns an array of all the tracked services. The number of tracked services is re-
turned by the size method.
• getServices(T[]) - Like getServices() but provides a convenient way to get these services into a
correctly typed array.
• getServiceReference() - Returns a ServiceReference object for one of the services being tracked.
The service object for this service may be returned by calling the ServiceTracker object's getSer-
vice() method.
• getServiceReferences() - Returns a list of the ServiceReference objects for services being tracked.
The service object for a specific tracked service may be returned by calling the ServiceTracker
object's getService(ServiceReference) method.
• waitForService(long) - Allows the caller to wait until at least one instance of a service is tracked
or until the time-out expires. If the time-out is zero, the caller must wait until at least one in-
stance of a service is tracked. waitForService must not used within the BundleActivator methods,
as these methods are expected to complete in a short period of time. A Framework could wait for
the start method to complete before starting the bundle that registers the service for which the
caller is waiting, creating a deadlock situation.
• remove(ServiceReference) - This method may be used to remove a specific service from being
tracked by the ServiceTracker object, causing removedService to be called for that service.
• close() - This method must remove all services being tracked by the ServiceTracker object, caus-
ing removedService to be called for all tracked services.
• getTrackingCount() - A Service Tracker can have services added, modified, or removed at any mo-
ment in time. The getTrackingCount method is intended to efficiently detect changes in a Ser-
vice Tracker. Every time the Service Tracker is changed, it must increase the tracking count.
• isEmpty() - To detect that the tracker has no tracked services.
• getTracked() - Return the tracked objects.
When a service is being added to the ServiceTracker object or when a tracked service is modified
or removed from the ServiceTracker object, it must call addingService, modifiedService, or re-
movedService, respectively, on the ServiceTrackerCustomizer object (if specified when the Service-
Tracker object was created); otherwise it must call these methods on itself.
A bundle developer may customize the action when a service is tracked. Another reason for cus-
tomizing the ServiceTracker class is to programmatically select which services are tracked. A filter
may not sufficiently specify the services that the bundle developer is interested in tracking. By im-
plementing addingService, the bundle developer can use additional runtime information to deter-
mine if the service should be tracked. If null is returned by the addingService method, the service
must not be tracked.
Finally, the bundle developer can return a specialized object from addingService that differs from
the service object. This specialized object could contain the service object and any associated infor-
mation. This returned object is then tracked instead of the service object. When the removedService
method is called, the object that is passed along with the ServiceReference object is the one that was
returned from the earlier call to the addingService method.
new ServiceTracker<HttpService,MyServlet>(context,HttpService.class,null){
public MyServlet addingService( ServiceReference<HttpService>reference) {
HttpService svc = context.getService(reference);
MyServlet ms = new MyServlet(scv); return ms;
}
public void removedService( ServiceReference<HttpService>reference,
MyServlet ms) {
ms.close();
context.ungetService(reference);
}
}
In this example, the service type is the HttpService class and the wrapper type is the servlet.
701.4.2 Constructor
The BundleTracker interface defines the following constructors to create BundleTracker objects:
A new BundleTracker object must not begin tracking services until its open method is called.
• open() - Start tracking the bundles, callbacks can occur before this method is called.
It is necessary to parse the Http-Mapper header. Regular expression allow this to be done very con-
cise.
The Bundle Tracker requires a specialized constructor. This example only works for active bundles.
This implies that a bundle only provides contents when it is started, enabling an administrator to
control the availability.
The following method implements the callback from the Bundle Tracker when a new bundle is dis-
covered. In this method a specialized HttpContext object is created that knows how to retrieve its re-
sources from the bundle that was just discovered. This context is registered with the Http Service. If
no header is found null is returned so that non-participating bundles are no longer tracked.
The modifiedBundle method does not have to be implemented because this example is not inter-
ested in state changes because the only state of interest is the ACTIVE state. Therefore, the remain-
ing method left to implement is the removedBundle method. If the wrapper object is non-null then
we need to unregister the alias to prevent collisions in the http namespace when the bundle is rein-
stalled or updated.
The remaining methods would be unnecessary if the Extender class had extended the BundleTracker
class. The BundleTrackerCustomizer interface requires a dummy implementation of the modified-
Bundle method:
It is usually not a good idea to start a tracker in a constructor because opening a service tracker will
immediately cause a number of callbacks for the existing bundles. If the Extender class was sub-
classed, then this could call back the uninitialized sub class methods. It is therefore better to sepa-
rate the initialization from the opening. There is therefore a need for an open and close method.
The previous example uses an HttpContext subclass that can retrieve resources from the target bun-
dle:
701.5 Security
A tracker contains a BundleContext instance variable that is accessible to the methods in a subclass.
A BundleContext object should never be given to other bundles because it is a capability. The frame-
work makes allocations based on the bundle context with respect to security and resource manage-
ment.
The tracker implementations do not have a method to get the BundleContext object, however, sub-
classes should be careful not to provide such a method if the tracker is given to other bundles.
The services that are being tracked are available via a ServiceTracker . These services are dependent
on the BundleContext as well. It is therefore necessary to do a careful security analysis when Ser-
viceTracker objects are given to other bundles. The same counts for the Bundle Tracker. It is strongly
advised to not pass trackers to other bundles.
701.6 org.osgi.util.tracker
Tracker Package Version 1.5.
Bundles wishing to use this package must list the package in the Import-Package header of the
bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.util.tracker; version="[1.5,2.0)"
701.6.1 Summary
• BundleTracker - The BundleTracker class simplifies tracking bundles much like the Service-
Tracker simplifies tracking services.
• BundleTrackerCustomizer - The BundleTrackerCustomizer interface allows a BundleTracker to
customize the Bundles that are tracked.
• ServiceTracker - The ServiceTracker class simplifies using services from the Framework's ser-
vice registry.
• ServiceTrackerCustomizer - The ServiceTrackerCustomizer interface allows a ServiceTracker to
customize the service objects that are tracked.
event The bundle event which caused this customizer method to be called or null if there is no bundle
event associated with the call to this method.
□ Default implementation of the BundleTrackerCustomizer.addingBundle method.
This method is only called when this BundleTracker has been constructed with a null BundleTrack-
erCustomizer argument.
This implementation simply returns the specified Bundle.
This method can be overridden in a subclass to customize the object to be tracked for the bundle be-
ing added.
Returns The specified bundle.
See Also BundleTrackerCustomizer.addingBundle(Bundle, BundleEvent)
Since 1.5
customizer The customizer object to call when services are added, modified, or removed in this ServiceTrack-
er. If customizer is null, then this ServiceTracker will be used as the ServiceTrackerCustomizer and
this ServiceTracker will call the ServiceTrackerCustomizer methods on itself.
□ Create a ServiceTracker on the specified Filter object.
Services which match the specified Filter object will be tracked by this ServiceTracker .
Since 1.1
If any services are being tracked, this implementation returns the result of calling
getService(getServiceReference()).
Returns A service object or null if no services are being tracked.
□ Remove a service from this ServiceTracker . The specified service will be removed
from this ServiceTracker . If the specified service was being tracked then the
ServiceTrackerCustomizer.removedService method will be called for that service.
Concurrency Thread-safe
End Of Document