Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2016-12-07 11:02:27 -0500
committerThomas Watson2017-01-11 11:08:16 -0500
commit86ac868ae86d1ff21292919d47a6dbf46075d3a8 (patch)
tree54e19a5e50b418afc9c8ecd4d21d775c257ffee6
parentdd171a7ac305c0b5df769731037a76bf645d797e (diff)
downloadrt.equinox.framework-86ac868ae86d1ff21292919d47a6dbf46075d3a8.tar.gz
rt.equinox.framework-86ac868ae86d1ff21292919d47a6dbf46075d3a8.tar.xz
rt.equinox.framework-86ac868ae86d1ff21292919d47a6dbf46075d3a8.zip
Bug 501950 - [ds] replace Equinox DS implementation with Felix SCR (DS)I20170112-0245I20170112-0200I20170111-2000
implementation Update the DS API for R6 Change-Id: I49f46a8474a4b434ad20fe54f2ad8f0f4d649e99 Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.osgi.services/.settings/.api_filters49
-rw-r--r--bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF44
-rw-r--r--bundles/org.eclipse.osgi.services/pom.xml2
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java28
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java58
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java4
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java6
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentServiceObjects.java95
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java8
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java136
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java8
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/FieldOption.java53
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java8
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java263
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceScope.java57
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ServiceScope.java63
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java4
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo2
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java8
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo2
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/ServiceComponentRuntime.java165
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java113
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java171
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ReferenceDTO.java148
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/SatisfiedReferenceDTO.java62
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/UnsatisfiedReferenceDTO.java64
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/package-info.java42
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/package-info.java42
-rw-r--r--bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/appadmin/ApplicationAdminTest.java6
-rw-r--r--bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF18
-rw-r--r--bundles/org.eclipse.osgi.util/build.properties3
-rw-r--r--bundles/org.eclipse.osgi.util/lib/osgi.annotation.jarbin0 -> 13199 bytes
-rw-r--r--bundles/org.eclipse.osgi.util/pom.xml2
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Function.java43
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Predicate.java43
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/function/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/function/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Deferred.java142
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/FailedPromisesException.java55
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Failure.java61
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promise.java403
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/PromiseImpl.java615
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java180
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Success.java69
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/package-info.java40
-rw-r--r--bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/packageinfo1
-rw-r--r--bundles/org.eclipse.osgi/META-INF/MANIFEST.MF66
49 files changed, 3295 insertions, 200 deletions
diff --git a/bundles/org.eclipse.osgi.services/.settings/.api_filters b/bundles/org.eclipse.osgi.services/.settings/.api_filters
new file mode 100644
index 000000000..ab34f1b57
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/.settings/.api_filters
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.osgi.services" version="2">
+ <resource path="META-INF/MANIFEST.MF">
+ <filter id="923795461">
+ <message_arguments>
+ <message_argument value="3.6.0"/>
+ <message_argument value="3.5.100"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="META-INF/MANIFEST.MF" type="org.osgi.service.component.annotations.Component">
+ <filter id="286375965">
+ <message_arguments>
+ <message_argument value="org.osgi.service.component.annotations.Component"/>
+ <message_argument value="reference()"/>
+ </message_arguments>
+ </filter>
+ <filter id="288469092">
+ <message_arguments>
+ <message_argument value="org.osgi.service.component.annotations.Component"/>
+ <message_argument value="configurationPid()"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/osgi/service/component/ComponentConstants.java" type="org.osgi.service.component.ComponentConstants">
+ <filter id="403767336">
+ <message_arguments>
+ <message_argument value="org.osgi.service.component.ComponentConstants"/>
+ <message_argument value="COMPONENT_CAPABILITY_NAME"/>
+ </message_arguments>
+ </filter>
+ <filter id="1209008130">
+ <message_arguments>
+ <message_argument value="1.3"/>
+ <message_argument value="3.6"/>
+ <message_argument value="COMPONENT_CAPABILITY_NAME"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/osgi/service/component/ComponentServiceObjects.java" type="org.osgi.service.component.ComponentServiceObjects">
+ <filter id="1108344834">
+ <message_arguments>
+ <message_argument value="1.3"/>
+ <message_argument value="3.6"/>
+ <message_argument value="org.osgi.service.component.ComponentServiceObjects"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
index b71f95ab0..6527349a5 100644
--- a/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.services/META-INF/MANIFEST.MF
@@ -2,36 +2,40 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %osgiServices
Bundle-SymbolicName: org.eclipse.osgi.services
-Bundle-Version: 3.5.100.qualifier
+Bundle-Version: 3.6.0.qualifier
Bundle-Description: %osgiServicesDes
Bundle-Localization: plugin
Bundle-Vendor: %eclipse.org
Bundle-DocUrl: http://www.eclipse.org
Bundle-ContactAddress: www.eclipse.org
-Export-Package: org.osgi.service.cm; version="1.5",
- org.osgi.service.component; version="1.2.2",
- org.osgi.service.component.annotations; version="1.2",
- org.osgi.service.device; version="1.1",
- org.osgi.service.event; version="1.3.1",
- org.osgi.service.http;version="1.2.1",
- org.osgi.service.http.context;version="1.0",
- org.osgi.service.http.runtime;version="1.0",
- org.osgi.service.http.runtime.dto;version="1.0",
+Export-Package: org.osgi.service.cm;version="1.5";uses:="org.osgi.framework",
+ org.osgi.service.component;version="1.3";uses:="org.osgi.framework",
+ org.osgi.service.component.annotations;version="1.3",
+ org.osgi.service.component.runtime;version="1.3";uses:="org.osgi.framework,org.osgi.util.promise,org.osgi.service.component.runtime.dto",
+ org.osgi.service.component.runtime.dto;version="1.3";uses:="org.osgi.dto,org.osgi.framework.dto",
+ org.osgi.service.device;version="1.1";uses:="org.osgi.framework",
+ org.osgi.service.event;version="1.3.1";uses:="org.osgi.framework",
+ org.osgi.service.http;version="1.2.1";uses:="javax.servlet,javax.servlet.http",
+ org.osgi.service.http.context;version="1.0";uses:="org.osgi.framework,javax.servlet.http",
+ org.osgi.service.http.runtime;version="1.0";uses:="org.osgi.service.http.runtime.dto",
+ org.osgi.service.http.runtime.dto;version="1.0";uses:="org.osgi.dto,org.osgi.framework.dto",
org.osgi.service.http.whiteboard;version="1.0",
- org.osgi.service.log; version="1.3",
- org.osgi.service.metatype; version="1.3",
- org.osgi.service.provisioning; version="1.2",
- org.osgi.service.upnp; version="1.2",
- org.osgi.service.useradmin; version="1.1",
- org.osgi.service.wireadmin; version="1.0.1"
+ org.osgi.service.log;version="1.3";uses:="org.osgi.framework",
+ org.osgi.service.metatype;version="1.3";uses:="org.osgi.framework",
+ org.osgi.service.provisioning;version="1.2",
+ org.osgi.service.upnp;version="1.2",
+ org.osgi.service.useradmin;version="1.1";uses:="org.osgi.framework",
+ org.osgi.service.wireadmin;version="1.0.1";uses:="org.osgi.framework"
Import-Package: javax.servlet;resolution:=optional,
javax.servlet.http;resolution:=optional,
org.osgi.dto;version="1.0",
org.osgi.framework;version="1.6",
org.osgi.framework.dto;version="1.8.0",
org.osgi.service.cm;version="[1.5,1.6)",
- org.osgi.service.component;version="[1.2,1.3)",
- org.osgi.service.component.annotations;version="[1.2,1.3)",
+ org.osgi.service.component;version="[1.3,1.4)",
+ org.osgi.service.component.annotations;version="[1.3,1.4)",
+ org.osgi.service.component.runtime; version="[1.3,1.4)",
+ org.osgi.service.component.runtime.dto; version="[1.3,1.4)",
org.osgi.service.device;version="[1.1,1.2)",
org.osgi.service.event;version="[1.3,1.4)",
org.osgi.service.http;version="[1.2,1.3)",
@@ -40,7 +44,9 @@ Import-Package: javax.servlet;resolution:=optional,
org.osgi.service.provisioning;version="[1.2,1.3)",
org.osgi.service.upnp;version="[1.2,1.3)",
org.osgi.service.useradmin;version="[1.1,1.2)",
- org.osgi.service.wireadmin;version="[1.0,1.1)"
+ org.osgi.service.wireadmin;version="[1.0,1.1)",
+ org.osgi.util.function;version="[1.0,2.0)",
+ org.osgi.util.promise;version="[1.0,2.0)"
DynamicImport-Package: javax.servlet,
javax.servlet.http
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/bundles/org.eclipse.osgi.services/pom.xml b/bundles/org.eclipse.osgi.services/pom.xml
index bead54ccb..167274b43 100644
--- a/bundles/org.eclipse.osgi.services/pom.xml
+++ b/bundles/org.eclipse.osgi.services/pom.xml
@@ -19,7 +19,7 @@
</parent>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
- <version>3.5.100-SNAPSHOT</version>
+ <version>3.6.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>
<plugins>
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java
index ac753054f..624eb5610 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2015). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,11 +47,11 @@ public interface ComponentConstants {
* configuration. The value of this property must be of type {@code Long}.
*
* <p>
- * The value of this property is assigned by the Service Component Runtime
- * when a component configuration is created. The Service Component Runtime
- * assigns a unique value that is larger than all previously assigned values
- * since the Service Component Runtime was started. These values are NOT
- * persistent across restarts of the Service Component Runtime.
+ * The value of this property is assigned by Service Component Runtime when
+ * a component configuration is created. Service Component Runtime assigns a
+ * unique value that is larger than all previously assigned values since
+ * Service Component Runtime was started. These values are NOT persistent
+ * across restarts of Service Component Runtime.
*/
public final static String COMPONENT_ID = "component.id";
@@ -123,4 +123,20 @@ public interface ComponentConstants {
* @since 1.1
*/
public static final int DEACTIVATION_REASON_BUNDLE_STOPPED = 6;
+
+ /**
+ * Capability name for Service Component Runtime.
+ *
+ * <p>
+ * Used in {@code Provide-Capability} and {@code Require-Capability}
+ * manifest headers with the {@code osgi.extender} namespace. For example:
+ *
+ * <pre>
+ * Require-Capability: osgi.extender;
+ * filter:="(&amp;(osgi.extender=osgi.component)(version&gt;=1.3)(!(version&gt;=2.0)))"
+ * </pre>
+ *
+ * @since 1.3
+ */
+ public static final String COMPONENT_CAPABILITY_NAME = "osgi.component";
}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java
index 9855c2af8..549969184 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,26 +28,8 @@ import org.osgi.framework.ServiceReference;
* component instance has a unique Component Context.
*
* <p>
- * A component instance may have an activate method. If a component instance has
- * a suitable and accessible activate method, this method will be called when a
- * component configuration is activated. If the activate method takes a
- * {@code ComponentContext} argument, it will be passed the component instance's
- * Component Context object. If the activate method takes a
- * {@code BundleContext} argument, it will be passed the component instance's
- * Bundle Context object. If the activate method takes a {@code Map} argument,
- * it will be passed an unmodifiable Map containing the component properties.
- *
- * <p>
- * A component instance may have a deactivate method. If a component instance
- * has a suitable and accessible deactivate method, this method will be called
- * when the component configuration is deactivated. If the deactivate method
- * takes a {@code ComponentContext} argument, it will be passed the component
- * instance's Component Context object. If the deactivate method takes a
- * {@code BundleContext} argument, it will be passed the component instance's
- * Bundle Context object. If the deactivate method takes a {@code Map} argument,
- * it will be passed an unmodifiable Map containing the component properties. If
- * the deactivate method takes an {@code int} or {@code Integer} argument, it
- * will be passed the reason code for the component instance's deactivation.
+ * A component instance may obtain its Component Context object through its
+ * activate, modified, and deactivate methods.
*
* @ThreadSafe
* @author $Id$
@@ -70,7 +52,7 @@ public interface ComponentContext {
* multiple services are bound to the reference, the service with the
* highest ranking (as specified in its {@code Constants.SERVICE_RANKING}
* property) is returned. If there is a tie in ranking, the service with the
- * lowest service ID (as specified in its {@code Constants.SERVICE_ID}
+ * lowest service id (as specified in its {@code Constants.SERVICE_ID}
* property); that is, the service that was registered first is returned.
*
* @param name The name of a reference as specified in a {@code reference}
@@ -78,7 +60,7 @@ public interface ComponentContext {
* @return A service object for the referenced service or {@code null} if
* the reference cardinality is {@code 0..1} or {@code 0..n} and no
* bound service is available.
- * @throws ComponentException If the Service Component Runtime catches an
+ * @throws ComponentException If Service Component Runtime catches an
* exception while activating the bound service.
*/
public Object locateService(String name);
@@ -87,6 +69,7 @@ public interface ComponentContext {
* Returns the service object for the specified reference name and
* {@code ServiceReference}.
*
+ * @param <S> Type of Service.
* @param name The name of a reference as specified in a {@code reference}
* element in this component's description.
* @param reference The {@code ServiceReference} to a bound service. This
@@ -95,10 +78,10 @@ public interface ComponentContext {
* @return A service object for the referenced service or {@code null} if
* the specified {@code ServiceReference} is not a bound service for
* the specified reference name.
- * @throws ComponentException If the Service Component Runtime catches an
+ * @throws ComponentException If Service Component Runtime catches an
* exception while activating the bound service.
*/
- public Object locateService(String name, ServiceReference<?> reference);
+ public <S> S locateService(String name, ServiceReference<S> reference);
/**
* Returns the service objects for the specified reference name.
@@ -110,7 +93,7 @@ public interface ComponentContext {
* {@code 0..n} and no bound service is available. If the reference
* cardinality is {@code 0..1} or {@code 1..1} and a bound service
* is available, the array will have exactly one element.
- * @throws ComponentException If the Service Component Runtime catches an
+ * @throws ComponentException If Service Component Runtime catches an
* exception while activating a bound service.
*/
public Object[] locateServices(String name);
@@ -126,17 +109,18 @@ public interface ComponentContext {
/**
* If the component instance is registered as a service using the
- * {@code servicefactory="true"} attribute, then this method returns the
- * bundle using the service provided by the component instance.
+ * {@code servicescope="bundle"} or {@code servicescope="prototype"}
+ * attribute, then this method returns the bundle using the service provided
+ * by the component instance.
* <p>
* This method will return {@code null} if:
* <ul>
* <li>The component instance is not a service, then no bundle can be using
* it as a service.</li>
* <li>The component instance is a service but did not specify the
- * {@code servicefactory="true"} attribute, then all bundles using the
- * service provided by the component instance will share the same component
- * instance.</li>
+ * {@code servicescope="bundle"} or {@code servicescope="prototype"}
+ * attribute, then all bundles using the service provided by the component
+ * instance will share the same component instance.</li>
* <li>The service provided by the component instance is not currently being
* used by any bundle.</li>
* </ul>
@@ -158,6 +142,12 @@ public interface ComponentContext {
* Enables the specified component name. The specified component name must
* be in the same bundle as this component.
*
+ * <p>
+ * This method must return after changing the enabled state of the specified
+ * component name. Any actions that result from this, such as activating or
+ * deactivating a component configuration, must occur asynchronously to this
+ * method call.
+ *
* @param name The name of a component or {@code null} to indicate all
* components in the bundle.
*/
@@ -167,6 +157,12 @@ public interface ComponentContext {
* Disables the specified component name. The specified component name must
* be in the same bundle as this component.
*
+ * <p>
+ * This method must return after changing the enabled state of the specified
+ * component name. Any actions that result from this, such as activating or
+ * deactivating a component configuration, must occur asynchronously to this
+ * method call.
+ *
* @param name The name of a component.
*/
public void disableComponent(String name);
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java
index 9ec6a42f2..6b4777460 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
package org.osgi.service.component;
/**
- * Unchecked exception which may be thrown by the Service Component Runtime.
+ * Unchecked exception which may be thrown by Service Component Runtime.
*
* @author $Id$
*/
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java
index efb1e1695..a6422fc51 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import org.osgi.annotation.versioning.ProviderType;
/**
* When a component is declared with the {@code factory} attribute on its
- * {@code component} element, the Service Component Runtime will register a
+ * {@code component} element, Service Component Runtime will register a
* Component Factory service to allow new component configurations to be created
* and activated rather than automatically creating and activating component
* configuration as necessary.
@@ -42,7 +42,7 @@ public interface ComponentFactory {
* configuration has been activated and, if the component specifies
* a {@code service} element, the component instance has been
* registered as a service.
- * @throws ComponentException If the Service Component Runtime is unable to
+ * @throws ComponentException If Service Component Runtime is unable to
* activate the component configuration.
*/
public ComponentInstance newInstance(Dictionary<String, ?> properties);
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentServiceObjects.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentServiceObjects.java
new file mode 100644
index 000000000..49fc5e863
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/ComponentServiceObjects.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Allows multiple service objects for a service to be obtained.
+ *
+ * <p>
+ * A component instance can receive a {@code ComponentServiceObjects} object via
+ * a reference that is typed {@code ComponentServiceObjects}.
+ *
+ * <p>
+ * For services with {@link Constants#SCOPE_PROTOTYPE prototype} scope, multiple
+ * service objects for the service can be obtained. For services with
+ * {@link Constants#SCOPE_SINGLETON singleton} or {@link Constants#SCOPE_BUNDLE
+ * bundle} scope, only one, use-counted service object is available.
+ *
+ * <p>
+ * Any unreleased service objects obtained from this
+ * {@code ComponentServiceObjects} object are automatically released by Service
+ * Component Runtime when the service becomes unbound.
+ *
+ * @param <S> Type of Service
+ * @ThreadSafe
+ * @since 1.3
+ * @see ServiceObjects
+ * @author $Id$
+ */
+@ProviderType
+public interface ComponentServiceObjects<S> {
+ /**
+ * Returns a service object for the {@link #getServiceReference()
+ * associated} service.
+ *
+ * <p>
+ * This method will always return {@code null} when the associated service
+ * has been become unbound.
+ *
+ * @return A service object for the associated service or {@code null} if
+ * the service is unbound, the customized service object returned by
+ * a {@code ServiceFactory} does not implement the classes under
+ * which it was registered or the {@code ServiceFactory} threw an
+ * exception.
+ * @throws IllegalStateException If the associated service has been become
+ * unbound.
+ * @see #ungetService(Object)
+ */
+ public S getService();
+
+ /**
+ * Releases a service object for the {@link #getServiceReference()
+ * associated} service.
+ *
+ * <p>
+ * The specified service object must no longer be used and all references to
+ * it should be destroyed after calling this method.
+ *
+ * @param service A service object previously provided by this
+ * {@code ComponentServiceObjects} object.
+ * @throws IllegalStateException If the associated service has been become
+ * unbound.
+ * @throws IllegalArgumentException If the specified service object was not
+ * provided by this {@code ComponentServiceObjects} object.
+ * @see #getService()
+ */
+ public void ungetService(S service);
+
+ /**
+ * Returns the {@link ServiceReference} for the service associated with this
+ * {@code ComponentServiceObjects} object.
+ *
+ * @return The {@link ServiceReference} for the service associated with this
+ * {@code ComponentServiceObjects} object.
+ */
+ public ServiceReference<S> getServiceReference();
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java
index e24a899f7..6e320f371 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Activate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,9 +29,9 @@ import java.lang.annotation.Target;
* The annotated method is the activate method of the Component.
*
* <p>
- * This annotation is not processed at runtime by a Service Component Runtime
- * implementation. It must be processed by tools and used to add a Component
- * Description to the bundle.
+ * This annotation is not processed at runtime by Service Component Runtime. It
+ * must be processed by tools and used to add a Component Description to the
+ * bundle.
*
* @see "The activate attribute of the component element of a Component Description."
* @author $Id$
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java
index e7f072364..d44af93dc 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Component.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2015). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,9 +28,9 @@ import java.lang.annotation.Target;
* The annotated class is the implementation class of the Component.
*
* <p>
- * This annotation is not processed at runtime by a Service Component Runtime
- * implementation. It must be processed by tools and used to add a Component
- * Description to the bundle.
+ * This annotation is not processed at runtime by Service Component Runtime. It
+ * must be processed by tools and used to add a Component Description to the
+ * bundle.
*
* @see "The component element of a Component Description."
* @author $Id$
@@ -82,11 +82,16 @@ public @interface Component {
* component instance.
*
* <p>
- * If {@code true}, this Component uses the OSGi ServiceFactory concept. If
- * {@code false} or not specified, this Component does not use the OSGi
- * ServiceFactory concept.
+ * This element is ignored when the {@link #scope()} element does not have
+ * the default value. If {@code true}, this Component uses
+ * {@link ServiceScope#BUNDLE bundle} service scope. If {@code false} or not
+ * specified, this Component uses {@link ServiceScope#SINGLETON singleton}
+ * service scope. If the {@link #factory()} element is specified or the
+ * {@link #immediate()} element is specified with {@code true}, this element
+ * can only be specified with {@code false}.
*
- * @see "The servicefactory attribute of the service element of a Component Description."
+ * @see "The scope attribute of the service element of a Component Description."
+ * @deprecated Since 1.3. Replaced by {@link #scope()}.
*/
boolean servicefactory() default false;
@@ -95,8 +100,8 @@ public @interface Component {
* is started.
*
* <p>
- * If {@code true}, this Component is enabled. If {@code false} or not
- * specified, this Component is disabled.
+ * If {@code true} or not specified, this Component is enabled. If
+ * {@code false}, this Component is disabled.
*
* @see "The enabled attribute of the component element of a Component Description."
*/
@@ -110,13 +115,13 @@ public @interface Component {
* If {@code true}, this Component must be immediately activated upon
* becoming satisfied. If {@code false}, activation of this Component is
* delayed. If this property is specified, its value must be {@code false}
- * if the {@link #factory} property is also specified or must be
- * {@code true} if the {@link #service} property is specified with an empty
- * value.
+ * if the {@link #factory()} property is also specified or must be
+ * {@code true} if the {@link #service()} property is specified with an
+ * empty value.
*
* <p>
- * If not specified, the default is {@code false} if the {@link #factory}
- * property is specified or the {@link #service} property is not specified
+ * If not specified, the default is {@code false} if the {@link #factory()}
+ * property is specified or the {@link #service()} property is not specified
* or specified with a non-empty value and {@code true} otherwise.
*
* @see "The immediate attribute of the component element of a Component Description."
@@ -127,13 +132,14 @@ public @interface Component {
* Properties for this Component.
*
* <p>
- * Each property string is specified as {@code "key=value"}. The type of the
- * property value can be specified in the key as {@code key:type=value}. The
- * type must be one of the property types supported by the type attribute of
- * the property element of a Component Description.
+ * Each property string is specified as {@code "name=value"}. The type of
+ * the property value can be specified in the name as
+ * {@code name:type=value}. The type must be one of the property types
+ * supported by the type attribute of the property element of a Component
+ * Description.
*
* <p>
- * To specify a property with multiple values, use multiple key, value
+ * To specify a property with multiple values, use multiple name, value
* pairs. For example, {@code "foo=bar", "foo=baz"}.
*
* @see "The property element of a Component Description."
@@ -174,8 +180,18 @@ public @interface Component {
* Configuration object where the PID equals the name of the component.
*
* <p>
- * If not specified, the {@link ConfigurationPolicy#OPTIONAL OPTIONAL}
- * configuration policy is used.
+ * If not specified, the configuration policy is based upon whether the
+ * component is also annotated with the Meta Type
+ * {@link org.osgi.service.metatype.annotations.Designate Designate}
+ * annotation.
+ * <ul>
+ * <li>Not annotated with {@code Designate} - The configuration policy is
+ * {@link ConfigurationPolicy#OPTIONAL OPTIONAL}.</li>
+ * <li>Annotated with {@code Designate(factory=false)} - The configuration
+ * policy is {@link ConfigurationPolicy#OPTIONAL OPTIONAL}.</li>
+ * <li>Annotated with {@code Designate(factory=true)} - The configuration
+ * policy is {@link ConfigurationPolicy#REQUIRE REQUIRE}.</li>
+ * </ul>
*
* @see "The configuration-policy attribute of the component element of a Component Description."
* @since 1.1
@@ -183,18 +199,82 @@ public @interface Component {
ConfigurationPolicy configurationPolicy() default ConfigurationPolicy.OPTIONAL;
/**
- * The configuration PID for the configuration of this Component.
+ * The configuration PIDs for the configuration of this Component.
*
* <p>
- * Allows the configuration PID for this Component to be different than the
- * name of this Component.
+ * Each value specifies a configuration PID for this Component.
*
* <p>
- * If not specified, the name of this Component is used as the configuration
- * PID of this Component.
+ * If no value is specified, the name of this Component is used as the
+ * configuration PID of this Component.
+ *
+ * <p>
+ * A special string (<code>{@value #NAME}</code>) can be used to specify the
+ * name of the component as a configuration PID. The {@code NAME} constant
+ * holds this special string. For example:
+ *
+ * <pre>
+ * &#64;Component(configurationPid={"com.acme.system", Component.NAME})
+ * </pre>
+ *
+ * Tools creating a Component Description from this annotation must replace
+ * the special string with the actual name of this Component.
*
* @see "The configuration-pid attribute of the component element of a Component Description."
* @since 1.2
*/
- String configurationPid() default "";
+ String[] configurationPid() default NAME;
+
+ /**
+ * Special string representing the name of this Component.
+ *
+ * <p>
+ * This string can be used in {@link #configurationPid()} to specify the
+ * name of the component as a configuration PID. For example:
+ *
+ * <pre>
+ * &#64;Component(configurationPid={"com.acme.system", Component.NAME})
+ * </pre>
+ *
+ * Tools creating a Component Description from this annotation must replace
+ * the special string with the actual name of this Component.
+ *
+ * @since 1.3
+ */
+ String NAME = "$";
+
+ /**
+ * The service scope for the service of this Component.
+ *
+ * <p>
+ * If not specified (and the deprecated {@link #servicefactory()} element is
+ * not specified), the {@link ServiceScope#SINGLETON singleton} service
+ * scope is used. If the {@link #factory()} element is specified or the
+ * {@link #immediate()} element is specified with {@code true}, this element
+ * can only be specified with the {@link ServiceScope#SINGLETON singleton}
+ * service scope.
+ *
+ * @see "The scope attribute of the service element of a Component Description."
+ * @since 1.3
+ */
+ ServiceScope scope() default ServiceScope.DEFAULT;
+
+ /**
+ * The lookup strategy references of this Component.
+ *
+ * <p>
+ * To access references using the lookup strategy, {@link Reference}
+ * annotations are specified naming the reference and declaring the type of
+ * the referenced service. The referenced service can be accessed using one
+ * of the {@code locateService} methods of {@code ComponentContext}.
+ *
+ * <p>
+ * To access references using the event strategy, bind methods are annotated
+ * with {@link Reference}. To access references using the field strategy,
+ * fields are annotated with {@link Reference}.
+ *
+ * @see "The reference element of a Component Description."
+ * @since 1.3
+ */
+ Reference[] reference() default {};
}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java
index 1809c70eb..78bb6b4fe 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Deactivate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,9 +29,9 @@ import java.lang.annotation.Target;
* The annotated method is the deactivate method of the Component.
*
* <p>
- * This annotation is not processed at runtime by a Service Component Runtime
- * implementation. It must be processed by tools and used to add a Component
- * Description to the bundle.
+ * This annotation is not processed at runtime by Service Component Runtime. It
+ * must be processed by tools and used to add a Component Description to the
+ * bundle.
*
* @see "The deactivate attribute of the component element of a Component Description."
* @author $Id$
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/FieldOption.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/FieldOption.java
new file mode 100644
index 000000000..35bfd6c67
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/FieldOption.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) OSGi Alliance (2014, 2015). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.annotations;
+
+/**
+ * Field options for the {@link Reference} annotation.
+ *
+ * @since 1.3
+ * @author $Id$
+ */
+public enum FieldOption {
+
+ /**
+ * The update field option is used to update the collection referenced by
+ * the field when there are changes to the bound services.
+ *
+ * <p>
+ * This field option can only be used when the field reference has dynamic
+ * policy and multiple cardinality.
+ */
+ UPDATE("update"),
+
+ /**
+ * The replace field option is used to replace the field value with a new
+ * value when there are changes to the bound services.
+ */
+ REPLACE("replace");
+
+ private final String value;
+
+ FieldOption(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java
index fd9f97d2f..c4d0c68f2 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Modified.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,9 +29,9 @@ import java.lang.annotation.Target;
* The annotated method is the modified method of the Component.
*
* <p>
- * This annotation is not processed at runtime by a Service Component Runtime
- * implementation. It must be processed by tools and used to add a Component
- * Description to the bundle.
+ * This annotation is not processed at runtime by Service Component Runtime. It
+ * must be processed by tools and used to add a Component Description to the
+ * bundle.
*
* @see "The modified attribute of the component element of a Component Description."
* @author $Id$
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java
index 9887c51c7..b13bbef27 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/Reference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2013). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2014). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,16 +22,17 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Identify the annotated method as a {@code bind} method of a Service
- * Component.
+ * Identify the annotated member as a reference of a Service Component.
*
* <p>
- * The annotated method is a bind method of the Component.
+ * When the annotation is applied to a method, the method is the bind method of
+ * the reference. When the annotation is applied to a field, the field will
+ * contain the bound service(s) of the reference.
*
* <p>
- * This annotation is not processed at runtime by a Service Component Runtime
- * implementation. It must be processed by tools and used to add a Component
- * Description to the bundle.
+ * This annotation is not processed at runtime by Service Component Runtime. It
+ * must be processed by tools and used to add a Component Description to the
+ * bundle.
*
* <p>
* In the generated Component Description for a component, the references must
@@ -42,111 +43,273 @@ import java.lang.annotation.Target;
* @author $Id$
*/
@Retention(RetentionPolicy.CLASS)
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Reference {
/**
* The name of this reference.
*
* <p>
- * If not specified, the name of this reference is based upon the name of
- * the method being annotated. If the method name begins with {@code bind},
- * {@code set} or {@code add}, that is removed.
+ * The name of this reference must be specified when using this annotation
+ * in the {@link Component#reference()} element since there is no annotated
+ * member from which the name can be determined.
+ *
+ * If not specified, the name of this reference is based upon how this
+ * annotation is used:
+ * <ul>
+ * <li>Annotated method - If the method name begins with {@code bind},
+ * {@code set} or {@code add}, that prefix is removed to create the name of
+ * the reference. Otherwise, the name of the reference is the method name.</li>
+ * <li>Annotated field - The name of the reference is the field name.</li>
+ * </ul>
*
* @see "The name attribute of the reference element of a Component Description."
*/
String name() default "";
/**
- * The type of the service to bind to this reference.
+ * The type of the service for this reference.
+ *
+ * <p>
+ * The type of the service for this reference must be specified when using
+ * this annotation in the {@link Component#reference()} element since there
+ * is no annotated member from which the type of the service can be
+ * determined.
*
* <p>
- * If not specified, the type of the service to bind is based upon the type
- * of the first argument of the method being annotated.
+ * If not specified, the type of the service for this reference is based
+ * upon how this annotation is used:
+ * <ul>
+ * <li>Annotated method - The type of the service is the type of the first
+ * argument of the method.</li>
+ * <li>Annotated field - The type of the service is based upon the type of
+ * the field being annotated and the cardinality of the reference. If the
+ * cardinality is either {@link ReferenceCardinality#MULTIPLE 0..n}, or
+ * {@link ReferenceCardinality#AT_LEAST_ONE 1..n}, the type of the field
+ * must be one of {@code java.util.Collection}, {@code java.util.List}, or a
+ * subtype of {@code java.util.Collection} so the type of the service is the
+ * generic type of the collection. Otherwise, the type of the service is the
+ * type of the field.</li>
+ * </ul>
*
* @see "The interface attribute of the reference element of a Component Description."
*/
Class<?> service() default Object.class;
/**
- * The cardinality of the reference.
+ * The cardinality of this reference.
*
* <p>
- * If not specified, the reference has a
- * {@link ReferenceCardinality#MANDATORY 1..1} cardinality.
+ * If not specified, the cardinality of this reference is based upon how
+ * this annotation is used:
+ * <ul>
+ * <li>Annotated method - The cardinality is
+ * {@link ReferenceCardinality#MANDATORY 1..1}.</li>
+ * <li>Annotated field - The cardinality is based on the type of the field.
+ * If the type is either {@code java.util.Collection},
+ * {@code java.util.List}, or a subtype of {@code java.util.Collection}, the
+ * cardinality is {@link ReferenceCardinality#MULTIPLE 0..n}. Otherwise the
+ * cardinality is {@link ReferenceCardinality#MANDATORY 1..1}.</li>
+ * <li>{@link Component#reference()} element - The cardinality is
+ * {@link ReferenceCardinality#MANDATORY 1..1}.</li>
+ * </ul>
*
* @see "The cardinality attribute of the reference element of a Component Description."
*/
ReferenceCardinality cardinality() default ReferenceCardinality.MANDATORY;
/**
- * The policy for the reference.
+ * The policy for this reference.
*
* <p>
- * If not specified, the {@link ReferencePolicy#STATIC STATIC} reference
- * policy is used.
+ * If not specified, the policy of this reference is based upon how this
+ * annotation is used:
+ * <ul>
+ * <li>Annotated method - The policy is {@link ReferencePolicy#STATIC
+ * STATIC}.</li>
+ * <li>Annotated field - The policy is based on the modifiers of the field.
+ * If the field is declared {@code volatile}, the policy is
+ * {@link ReferencePolicy#DYNAMIC}. Otherwise the policy is
+ * {@link ReferencePolicy#STATIC STATIC}.</li>
+ * <li>{@link Component#reference()} element - The policy is
+ * {@link ReferencePolicy#STATIC STATIC}.</li>
+ * </ul>
*
* @see "The policy attribute of the reference element of a Component Description."
*/
ReferencePolicy policy() default ReferencePolicy.STATIC;
/**
- * The target filter for the reference.
+ * The target property for this reference.
+ *
+ * <p>
+ * If not specified, no target property is set.
*
* @see "The target attribute of the reference element of a Component Description."
*/
String target() default "";
/**
- * The name of the unbind method which is associated with the annotated bind
- * method.
+ * The policy option for this reference.
*
* <p>
- * To declare no unbind method, the value {@code "-"} must be used.
+ * If not specified, the {@link ReferencePolicyOption#RELUCTANT RELUCTANT}
+ * reference policy option is used.
+ *
+ * @see "The policy-option attribute of the reference element of a Component Description."
+ * @since 1.2
+ */
+ ReferencePolicyOption policyOption() default ReferencePolicyOption.RELUCTANT;
+
+ /**
+ * The reference scope for this reference.
*
* <p>
- * If not specified, the name of the unbind method is derived from the name
- * of the annotated bind method. If the annotated method name begins with
- * {@code bind}, {@code set} or {@code add}, that is replaced with
- * {@code unbind}, {@code unset} or {@code remove}, respectively, to derive
- * the unbind method name. Otherwise, {@code un} is prefixed to the
- * annotated method name to derive the unbind method name. The unbind method
- * is only set if the component type contains a method with the derived
- * name.
+ * If not specified, the {@link ReferenceScope#BUNDLE bundle} reference
+ * scope is used.
*
- * @see "The unbind attribute of the reference element of a Component Description."
+ * @see "The scope attribute of the reference element of a Component Description."
+ * @since 1.3
*/
- String unbind() default "";
+ ReferenceScope scope() default ReferenceScope.BUNDLE;
+
+ /* Method injection elements */
/**
- * The policy option for the reference.
+ * The name of the bind method for this reference.
*
* <p>
- * If not specified, the {@link ReferencePolicyOption#RELUCTANT RELUCTANT}
- * reference policy option is used.
+ * If specified and this reference annotates a method, the specified name
+ * must match the name of the annotated method.
*
- * @see "The policy-option attribute of the reference element of a Component Description."
- * @since 1.2
+ * <p>
+ * If not specified, the name of the bind method is based upon how this
+ * annotation is used:
+ * <ul>
+ * <li>Annotated method - The name of the annotated method is the name of
+ * the bind method.</li>
+ * <li>Annotated field - There is no bind method name.</li>
+ * <li>{@link Component#reference()} element - There is no bind method name.
+ * </li>
+ * </ul>
+ *
+ * <p>
+ * If there is a bind method name, the component must contain a method with
+ * that name.
+ *
+ * @see "The bind attribute of the reference element of a Component Description."
+ * @since 1.3
*/
- ReferencePolicyOption policyOption() default ReferencePolicyOption.RELUCTANT;
+ String bind() default "";
/**
- * The name of the updated method which is associated with the annotated
- * bind method.
+ * The name of the updated method for this reference.
*
* <p>
- * To declare no updated method, the value {@code "-"} must be used.
+ * If not specified, the name of the updated method is based upon how this
+ * annotation is used:
+ * <ul>
+ * <li>Annotated method - The name of the updated method is created from the
+ * name of the annotated method. If the name of the annotated method begins
+ * with {@code bind}, {@code set} or {@code add}, that prefix is replaced
+ * with {@code updated} to create the name candidate for the updated method.
+ * Otherwise, {@code updated} is prefixed to the name of the annotated
+ * method to create the name candidate for the updated method. If the
+ * component type contains a method with the candidate name, the candidate
+ * name is used as the name of the updated method. To declare no updated
+ * method when the component type contains a method with the candidate name,
+ * the value {@code "-"} must be used.</li>
+ * <li>Annotated field - There is no updated method name.</li>
+ * <li>{@link Component#reference()} element - There is no updated method
+ * name.</li>
+ * </ul>
*
* <p>
- * If not specified, the name of the updated method is derived from the name
- * of the annotated bind method. If the annotated method name begins with
- * {@code bind}, {@code set} or {@code add}, that is replaced with
- * {@code updated} to derive the updated method name. Otherwise,
- * {@code updated} is prefixed to the annotated method name to derive the
- * updated method name. The updated method is only set if the component type
- * contains a method with the derived name.
+ * If there is an updated method name, the component must contain a method
+ * with that name.
*
* @see "The updated attribute of the reference element of a Component Description."
* @since 1.2
*/
String updated() default "";
+
+ /**
+ * The name of the unbind method for this reference.
+ *
+ * <p>
+ * If not specified, the name of the unbind method is based upon how this
+ * annotation is used:
+ * <ul>
+ * <li>Annotated method - The name of the unbind method is created from the
+ * name of the annotated method. If the name of the annotated method begins
+ * with {@code bind}, {@code set} or {@code add}, that prefix is replaced
+ * with {@code unbind}, {@code unset} or {@code remove}, respectively, to
+ * create the name candidate for the unbind method. Otherwise, {@code un} is
+ * prefixed to the name of the annotated method to create the name candidate
+ * for the unbind method. If the component type contains a method with the
+ * candidate name, the candidate name is used as the name of the unbind
+ * method. To declare no unbind method when the component type contains a
+ * method with the candidate name, the value {@code "-"} must be used.</li>
+ * <li>Annotated field - There is no unbind method name.</li>
+ * <li>{@link Component#reference()} element - There is no unbind method
+ * name.</li>
+ * </ul>
+ *
+ * <p>
+ * If there is an unbind method name, the component must contain a method
+ * with that name.
+ *
+ * @see "The unbind attribute of the reference element of a Component Description."
+ */
+ String unbind() default "";
+
+ /* Field injection elements */
+
+ /**
+ * The name of the field for this reference.
+ *
+ * <p>
+ * If specified and this reference annotates a field, the specified name
+ * must match the name of the annotated field.
+ *
+ * <p>
+ * If not specified, the name of the field is based upon how this annotation
+ * is used:
+ * <ul>
+ * <li>Annotated method - There is no field name.</li>
+ * <li>Annotated field - The name of the annotated field is the name of the
+ * field.</li>
+ * <li>{@link Component#reference()} element - There is no field name.</li>
+ * </ul>
+ *
+ * <p>
+ * If there is a field name, the component must contain a field with that
+ * name.
+ *
+ * @see "The field attribute of the reference element of a Component Description."
+ * @since 1.3
+ */
+ String field() default "";
+
+ /**
+ * The field option for this reference.
+ *
+ * <p>
+ * If not specified, the field option is based upon how this annotation is
+ * used:
+ * <ul>
+ * <li>Annotated method - There is no field option.</li>
+ * <li>Annotated field - The field option is based upon the policy and
+ * cardinality of the reference and the modifiers of the field. If the
+ * policy is {@link ReferencePolicy#DYNAMIC}, the cardinality is
+ * {@link ReferenceCardinality#MULTIPLE 0..n} or
+ * {@link ReferenceCardinality#AT_LEAST_ONE 1..n}, and the field is declared
+ * {@code final}, the field option is {@link FieldOption#UPDATE}. Otherwise,
+ * the field option is {@link FieldOption#REPLACE}</li>
+ * <li>{@link Component#reference()} element - There is no field option.</li>
+ * </ul>
+ *
+ * @see "The field-option attribute of the reference element of a Component Description."
+ * @since 1.3
+ */
+ FieldOption fieldOption() default FieldOption.REPLACE;
}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceScope.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceScope.java
new file mode 100644
index 000000000..2a61ef265
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ReferenceScope.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.annotations;
+
+/**
+ * Reference scope for the {@link Reference} annotation.
+ *
+ * @author $Id$
+ * @since 1.3
+ */
+public enum ReferenceScope {
+ /**
+ * A single service object is used for all references to the service in this
+ * bundle.
+ */
+ BUNDLE("bundle"),
+
+ /**
+ * If the bound service has prototype service scope, then each instance of
+ * the component with this reference can receive a unique instance of the
+ * service. If the bound service does not have prototype service scope, then
+ * this reference scope behaves the same as {@link #BUNDLE}.
+ */
+ PROTOTYPE("prototype"),
+
+ /**
+ * Bound services must have prototype service scope. Each instance of the
+ * component with this reference can receive a unique instance of the
+ * service.
+ */
+ PROTOTYPE_REQUIRED("prototype_required");
+
+ private final String value;
+
+ ReferenceScope(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ServiceScope.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ServiceScope.java
new file mode 100644
index 000000000..3c43d5fea
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/ServiceScope.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.annotations;
+
+/**
+ * Service scope for the {@link Component} annotation.
+ *
+ * @author $Id$
+ * @since 1.3
+ */
+public enum ServiceScope {
+ /**
+ * When the component is registered as a service, it must be registered as a
+ * bundle scope service but only a single instance of the component must be
+ * used for all bundles using the service.
+ */
+ SINGLETON("singleton"),
+
+ /**
+ * When the component is registered as a service, it must be registered as a
+ * bundle scope service and an instance of the component must be created for
+ * each bundle using the service.
+ */
+ BUNDLE("bundle"),
+
+ /**
+ * When the component is registered as a service, it must be registered as a
+ * prototype scope service and an instance of the component must be created
+ * for each distinct request for the service.
+ */
+ PROTOTYPE("prototype"),
+
+ /**
+ * Default element value for annotation. This is used to distinguish the
+ * default value for an element and should not otherwise be used.
+ */
+ DEFAULT("<<default>>");
+
+ private final String value;
+
+ ServiceScope(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java
index dbfa48a1b..bcb93c6d8 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/package-info.java
@@ -15,7 +15,7 @@
*/
/**
- * Service Component Annotations Package Version 1.2.
+ * Service Component Annotations Package Version 1.3.
*
* <p>
* This package is not used at runtime. Annotated classes are processed by
@@ -24,7 +24,7 @@
* @author $Id$
*/
-@Version("1.2")
+@Version("1.3")
package org.osgi.service.component.annotations;
import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo
index ef7df68cb..0117a56c1 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/annotations/packageinfo
@@ -1 +1 @@
-version 1.2
+version 1.3
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java
index 4b472f45b..9c158e8fb 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/package-info.java
@@ -15,7 +15,7 @@
*/
/**
- * Service Component Package Version 1.2.
+ * Service Component Package Version 1.3.
*
* <p>
* Bundles wishing to use this package must list the package in the
@@ -26,16 +26,16 @@
* <p>
* Example import for consumers using the API in this package:
* <p>
- * {@code Import-Package: org.osgi.service.component; version="[1.2,2.0)"}
+ * {@code Import-Package: org.osgi.service.component; version="[1.3,2.0)"}
* <p>
* Example import for providers implementing the API in this package:
* <p>
- * {@code Import-Package: org.osgi.service.component; version="[1.2,1.3)"}
+ * {@code Import-Package: org.osgi.service.component; version="[1.3,1.4)"}
*
* @author $Id$
*/
-@Version("1.2.2")
+@Version("1.3")
package org.osgi.service.component;
import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo
index 19727573b..0117a56c1 100644
--- a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/packageinfo
@@ -1 +1 @@
-version 1.2.2
+version 1.3
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/ServiceComponentRuntime.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/ServiceComponentRuntime.java
new file mode 100644
index 000000000..59760dcd5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/ServiceComponentRuntime.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime;
+
+import java.util.Collection;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+import org.osgi.util.promise.Promise;
+
+/**
+ * The {@code ServiceComponentRuntime} service represents the Declarative
+ * Services actor, known as Service Component Runtime (SCR), that manages the
+ * service components and their life cycle. The {@code ServiceComponentRuntime}
+ * service allows introspection of the components managed by Service Component
+ * Runtime.
+ *
+ * <p>
+ * This service differentiates between a {@link ComponentDescriptionDTO} and a
+ * {@link ComponentConfigurationDTO}. A {@link ComponentDescriptionDTO} is a
+ * representation of a declared component description. A
+ * {@link ComponentConfigurationDTO} is a representation of an actual instance
+ * of a declared component description parameterized by component properties.
+ * <p>
+ *
+ * Access to this service requires the
+ * {@code ServicePermission[ServiceComponentRuntime, GET]} permission. It is
+ * intended that only administrative bundles should be granted this permission
+ * to limit access to the potentially intrusive methods provided by this
+ * service.
+ *
+ * @ThreadSafe
+ * @since 1.3
+ * @author $Id$
+ */
+@ProviderType
+public interface ServiceComponentRuntime {
+
+ /**
+ * Returns the component descriptions declared by the specified active
+ * bundles.
+ *
+ * <p>
+ * Only component descriptions from active bundles are returned. If the
+ * specified bundles have no declared components or are not active, an empty
+ * collection is returned.
+ *
+ * @param bundles The bundles whose declared component descriptions are to
+ * be returned. Specifying no bundles, or the equivalent of an empty
+ * {@code Bundle} array, will return the declared component
+ * descriptions from all active bundles.
+ * @return The declared component descriptions of the specified active
+ * {@code bundles}. An empty collection is returned if there are no
+ * component descriptions for the specified active bundles.
+ */
+ Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles);
+
+ /**
+ * Returns the {@link ComponentDescriptionDTO} declared with the specified name
+ * by the specified bundle.
+ *
+ * <p>
+ * Only component descriptions from active bundles are returned.
+ * {@code null} if no such component is declared by the given {@code bundle}
+ * or the bundle is not active.
+ *
+ * @param bundle The bundle declaring the component description. Must not be
+ * {@code null}.
+ * @param name The name of the component description. Must not be
+ * {@code null}.
+ * @return The declared component description or {@code null} if the
+ * specified bundle is not active or does not declare a component
+ * description with the specified name.
+ */
+ ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name);
+
+ /**
+ * Returns the component configurations for the specified component
+ * description.
+ *
+ * @param description The component description. Must not be {@code null}.
+ * @return A collection containing a snapshot of the current component
+ * configurations for the specified component description. An empty
+ * collection is returned if there are none.
+ */
+ Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description);
+
+ /**
+ * Returns whether the specified component description is currently enabled.
+ *
+ * <p>
+ * The enabled state of a component description is initially set by the
+ * {@link ComponentDescriptionDTO#defaultEnabled enabled} attribute of the
+ * component description.
+ *
+ * @param description The component description. Must not be {@code null}.
+ * @return {@code true} if the specified component description is currently
+ * enabled. Otherwise, {@code false}.
+ * @see #enableComponent(ComponentDescriptionDTO)
+ * @see #disableComponent(ComponentDescriptionDTO)
+ * @see ComponentContext#disableComponent(String)
+ * @see ComponentContext#enableComponent(String)
+ */
+ boolean isComponentEnabled(ComponentDescriptionDTO description);
+
+ /**
+ * Enables the specified component description.
+ *
+ * <p>
+ * If the specified component description is currently enabled, this method
+ * has no effect.
+ *
+ * <p>
+ * This method must return after changing the enabled state of the specified
+ * component description. Any actions that result from this, such as
+ * activating or deactivating a component configuration, must occur
+ * asynchronously to this method call.
+ *
+ * @param description The component description to enable. Must not be
+ * {@code null}.
+ * @return A promise that will be resolved when the actions that result from
+ * changing the enabled state of the specified component have
+ * completed.
+ * @see #isComponentEnabled(ComponentDescriptionDTO)
+ */
+ Promise<Void> enableComponent(ComponentDescriptionDTO description);
+
+ /**
+ * Disables the specified component description.
+ *
+ * <p>
+ * If the specified component description is currently disabled, this method
+ * has no effect.
+ *
+ * <p>
+ * This method must return after changing the enabled state of the specified
+ * component description. Any actions that result from this, such as
+ * activating or deactivating a component configuration, must occur
+ * asynchronously to this method call.
+ *
+ * @param description The component description to disable. Must not be
+ * {@code null}.
+ * @return A promise that will be resolved when the actions that result from
+ * changing the enabled state of the specified component have
+ * completed.
+ * @see #isComponentEnabled(ComponentDescriptionDTO)
+ */
+ Promise<Void> disableComponent(ComponentDescriptionDTO description);
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java
new file mode 100644
index 000000000..a3e98bbac
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * A representation of an actual instance of a declared component description
+ * parameterized by component properties.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id$
+ */
+public class ComponentConfigurationDTO extends DTO {
+ /**
+ * The component configuration is unsatisfied due to a missing required
+ * configuration.
+ */
+ public static final int UNSATISFIED_CONFIGURATION = 1;
+
+ /**
+ * The component configuration is unsatisfied due to an unsatisfied
+ * reference.
+ */
+ public static final int UNSATISFIED_REFERENCE = 2;
+
+ /**
+ * The component configuration is satisfied.
+ *
+ * <p>
+ * Any {@link ComponentDescriptionDTO#serviceInterfaces services} declared
+ * by the component description are registered.
+ */
+ public static final int SATISFIED = 4;
+
+ /**
+ * The component configuration is active.
+ *
+ * <p>
+ * This is the normal operational state of a component configuration.
+ */
+ public static final int ACTIVE = 8;
+
+ /**
+ * The representation of the component configuration's component
+ * description.
+ */
+ public ComponentDescriptionDTO description;
+
+ /**
+ * The current state of the component configuration.
+ *
+ * <p>
+ * This is one of {@link #UNSATISFIED_CONFIGURATION},
+ * {@link #UNSATISFIED_REFERENCE}, {@link #SATISFIED} or {@link #ACTIVE}.
+ */
+ public int state;
+
+ /**
+ * The id of the component configuration.
+ *
+ * <p>
+ * The id is a non-persistent, unique value assigned at runtime. The id is
+ * also available as the {@code component.id} component property. The value
+ * of this field is unspecified if the state of this component configuration
+ * is unsatisfied.
+ */
+ public long id;
+
+ /**
+ * The component properties for the component configuration.
+ *
+ * @see ComponentContext#getProperties()
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The satisfied references.
+ *
+ * <p>
+ * Each {@link SatisfiedReferenceDTO} in the array represents a satisfied
+ * reference of the component configuration. The array must be empty if the
+ * component configuration has no satisfied references.
+ */
+ public SatisfiedReferenceDTO[] satisfiedReferences;
+
+ /**
+ * The unsatisfied references.
+ *
+ * <p>
+ * Each {@link UnsatisfiedReferenceDTO} in the array represents an
+ * unsatisfied reference of the component configuration. The array must be
+ * empty if the component configuration has no unsatisfied references.
+ */
+ public UnsatisfiedReferenceDTO[] unsatisfiedReferences;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java
new file mode 100644
index 000000000..9f098a6ed
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.BundleDTO;
+
+/**
+ * A representation of a declared component description.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id$
+ */
+public class ComponentDescriptionDTO extends DTO {
+ /**
+ * The name of the component.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code component}
+ * element. This must be the default name if the component description does
+ * not declare a name.
+ */
+ public String name;
+
+ /**
+ * The bundle declaring the component description.
+ */
+ public BundleDTO bundle;
+
+ /**
+ * The component factory name.
+ *
+ * <p>
+ * This is declared in the {@code factory} attribute of the
+ * {@code component} element. This must be {@code null} if the component
+ * description is not declared as a component factory.
+ */
+ public String factory;
+
+ /**
+ * The service scope.
+ *
+ * <p>
+ * This is declared in the {@code scope} attribute of the {@code service}
+ * element. This must be {@code null} if the component description does not
+ * declare any service interfaces.
+ */
+ public String scope;
+
+ /**
+ * The fully qualified name of the implementation class.
+ *
+ * <p>
+ * This is declared in the {@code class} attribute of the
+ * {@code implementation} element.
+ */
+ public String implementationClass;
+
+ /**
+ * The initial enabled state.
+ *
+ * <p>
+ * This is declared in the {@code enabled} attribute of the
+ * {@code component} element.
+ */
+ public boolean defaultEnabled;
+
+ /**
+ * The immediate state.
+ *
+ * <p>
+ * This is declared in the {@code immediate} attribute of the
+ * {@code component} element.
+ */
+ public boolean immediate;
+
+ /**
+ * The fully qualified names of the service interfaces.
+ *
+ * <p>
+ * These are declared in the {@code interface} attribute of the
+ * {@code provide} elements. The array must be empty if the component
+ * description does not declare any service interfaces.
+ */
+ public String[] serviceInterfaces;
+
+ /**
+ * The declared component properties.
+ *
+ * <p>
+ * These are declared in the {@code property} and {@code properties}
+ * elements.
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The referenced services.
+ *
+ * <p>
+ * These are declared in the {@code reference} elements. The array must be
+ * empty if the component description does not declare references to any
+ * services.
+ */
+ public ReferenceDTO[] references;
+
+ /**
+ * The name of the activate method.
+ *
+ * <p>
+ * This is declared in the {@code activate} attribute of the
+ * {@code component} element. This must be {@code null} if the component
+ * description does not declare an activate method name.
+ */
+ public String activate;
+
+ /**
+ * The name of the deactivate method.
+ *
+ * <p>
+ * This is declared in the {@code deactivate} attribute of the
+ * {@code component} element. This must be {@code null} if the component
+ * description does not declare a deactivate method name.
+ */
+ public String deactivate;
+
+ /**
+ * The name of the modified method.
+ *
+ * <p>
+ * This is declared in the {@code modified} attribute of the
+ * {@code component} element. This must be {@code null} if the component
+ * description does not declare a modified method name.
+ */
+ public String modified;
+
+ /**
+ * The configuration policy.
+ *
+ * <p>
+ * This is declared in the {@code configuration-policy} attribute of the
+ * {@code component} element. This must be the default configuration policy
+ * if the component description does not declare a configuration policy.
+ */
+ public String configurationPolicy;
+
+ /**
+ * The configuration pids.
+ *
+ * <p>
+ * These are declared in the {@code configuration-pid} attribute of the
+ * {@code component} element. This must contain the default configuration
+ * pid if the component description does not declare a configuration pid.
+ */
+ public String[] configurationPid;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ReferenceDTO.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ReferenceDTO.java
new file mode 100644
index 000000000..fca241327
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/ReferenceDTO.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2015). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.dto.DTO;
+
+/**
+ * A representation of a declared reference to a service.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id$
+ */
+public class ReferenceDTO extends DTO {
+
+ /**
+ * The name of the reference.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code reference}
+ * element. This must be the default name if the component description does
+ * not declare a name for the reference.
+ */
+ public String name;
+
+ /**
+ * The service interface of the reference.
+ *
+ * <p>
+ * This is declared in the {@code interface} attribute of the
+ * {@code reference} element.
+ */
+ public String interfaceName;
+
+ /**
+ * The cardinality of the reference.
+ *
+ * <p>
+ * This is declared in the {@code cardinality} attribute of the
+ * {@code reference} element. This must be the default cardinality if the
+ * component description does not declare a cardinality for the reference.
+ */
+ public String cardinality;
+
+ /**
+ * The policy of the reference.
+ *
+ * <p>
+ * This is declared in the {@code policy} attribute of the {@code reference}
+ * element. This must be the default policy if the component description
+ * does not declare a policy for the reference.
+ */
+ public String policy;
+
+ /**
+ * The policy option of the reference.
+ *
+ * <p>
+ * This is declared in the {@code policy-option} attribute of the
+ * {@code reference} element. This must be the default policy option if the
+ * component description does not declare a policy option for the reference.
+ */
+ public String policyOption;
+
+ /**
+ * The target of the reference.
+ *
+ * <p>
+ * This is declared in the {@code target} attribute of the {@code reference}
+ * element. This must be {@code null} if the component description does not
+ * declare a target for the reference.
+ */
+ public String target;
+
+ /**
+ * The name of the bind method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code bind} attribute of the {@code reference}
+ * element. This must be {@code null} if the component description does not
+ * declare a bind method for the reference.
+ */
+ public String bind;
+
+ /**
+ * The name of the unbind method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code unbind} attribute of the {@code reference}
+ * element. This must be {@code null} if the component description does not
+ * declare an unbind method for the reference.
+ */
+ public String unbind;
+
+ /**
+ * The name of the updated method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code updated} attribute of the
+ * {@code reference} element. This must be {@code null} if the component
+ * description does not declare an updated method for the reference.
+ */
+ public String updated;
+
+ /**
+ * The name of the field of the reference.
+ *
+ * <p>
+ * This is declared in the {@code field} attribute of the {@code reference}
+ * element. This must be {@code null} if the component description does not
+ * declare a field for the reference.
+ */
+ public String field;
+
+ /**
+ * The field option of the reference.
+ *
+ * <p>
+ * This is declared in the {@code field-option} attribute of the
+ * {@code reference} element. This must be {@code null} if the component
+ * description does not declare a field for the reference.
+ */
+ public String fieldOption;
+
+ /**
+ * The scope of the reference.
+ *
+ * <p>
+ * This is declared in the {@code scope} attribute of the {@code reference}
+ * element. This must be the default scope if the component description does
+ * not declare a scope for the reference.
+ */
+ public String scope;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/SatisfiedReferenceDTO.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/SatisfiedReferenceDTO.java
new file mode 100644
index 000000000..20de229ef
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/SatisfiedReferenceDTO.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+/**
+ * A representation of a satisfied reference.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id$
+ */
+public class SatisfiedReferenceDTO extends DTO {
+ /**
+ * The name of the declared reference.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code reference}
+ * element of the component description.
+ *
+ * @see ReferenceDTO#name
+ */
+ public String name;
+
+ /**
+ * The target property of the satisfied reference.
+ *
+ * <p>
+ * This is the value of the {@link ComponentConfigurationDTO#properties
+ * component property} whose name is the concatenation of the
+ * {@link ReferenceDTO#name declared reference name} and
+ * &quot;.target&quot;. This must be {@code null} if no target property is
+ * set for the reference.
+ */
+ public String target;
+
+ /**
+ * The bound services.
+ *
+ * <p>
+ * Each {@link ServiceReferenceDTO} in the array represents a service bound
+ * to the satisfied reference. The array must be empty if there are no bound
+ * services.
+ */
+ public ServiceReferenceDTO[] boundServices;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/UnsatisfiedReferenceDTO.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/UnsatisfiedReferenceDTO.java
new file mode 100644
index 000000000..20ce77a3d
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/UnsatisfiedReferenceDTO.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+/**
+ * A representation of an unsatisfied reference.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id$
+ */
+public class UnsatisfiedReferenceDTO extends DTO {
+ /**
+ * The name of the declared reference.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code reference}
+ * element of the component description.
+ *
+ * @see ReferenceDTO#name
+ */
+ public String name;
+
+ /**
+ * The target property of the unsatisfied reference.
+ *
+ * <p>
+ * This is the value of the {@link ComponentConfigurationDTO#properties
+ * component property} whose name is the concatenation of the
+ * {@link ReferenceDTO#name declared reference name} and
+ * &quot;.target&quot;. This must be {@code null} if no target property is
+ * set for the reference.
+ */
+ public String target;
+
+ /**
+ * The target services.
+ *
+ * <p>
+ * Each {@link ServiceReferenceDTO} in the array represents a target service
+ * for the reference. The array must be empty if there are no target
+ * services. The upper bound on the number of target services in the array
+ * is the upper bound on the {@link ReferenceDTO#cardinality cardinality} of
+ * the reference.
+ */
+ public ServiceReferenceDTO[] targetServices;
+}
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/package-info.java
new file mode 100644
index 000000000..d7d82da09
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service Component Runtime Data Transfer Objects Package Version 1.3.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime.dto; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime.dto; version="[1.3,1.4)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.3")
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/packageinfo
new file mode 100644
index 000000000..0117a56c1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/dto/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/package-info.java b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/package-info.java
new file mode 100644
index 000000000..3d4fa42ce
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2013). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service Component Runtime Package Version 1.3.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime; version="[1.3,1.4)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.3")
+package org.osgi.service.component.runtime;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/packageinfo b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/packageinfo
new file mode 100644
index 000000000..0117a56c1
--- /dev/null
+++ b/bundles/org.eclipse.osgi.services/src/org/osgi/service/component/runtime/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/appadmin/ApplicationAdminTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/appadmin/ApplicationAdminTest.java
index d5f681142..10e46111e 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/appadmin/ApplicationAdminTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/appadmin/ApplicationAdminTest.java
@@ -31,9 +31,10 @@ public class ApplicationAdminTest extends OSGiTest {
public static final String MODIFIED = "modified"; //$NON-NLS-1$
public static final String REMOVED = "removed"; //$NON-NLS-1$
public static final String simpleResults = "test.simpleResults"; //$NON-NLS-1$
- public static final String[] tests = new String[] {
- "testSimpleApp", "testInvalidArgs", "testAsyncValue01", "testAsyncValue02", "testAsyncValue03", "testAsyncValue04", "testAsyncValue05", "testAsyncValue06", "testExitValue01", "testExitValue02", "testExitValue03", "testExitValue04", "testExitValue05", "testExitValue06", "testExitValue07", "testExitValue08", "testExitValue09", "testExitValue10", "testGlobalSingleton", "testCardinality01", "testCardinality02", "testMainThreaded01", "testMainThreaded02", "testHandleEvents01", "testDescriptorEvents01", "testPersistentLock01", "testPersistentLock02", "testPersistentLock03", "testPersistentSchedule01", "testPersistentSchedule02", "testPersistentSchedule03", "testPersistentSchedule04", "testPersistentSchedule05", "testPersistentSchedule06", "testPersistentSchedule07", "testPersistentSchedule08", "testFailedApplication01", "testDestroyBeforeStart01", "testDestroyBeforeStart02"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ //$NON-NLS-20$ //$NON-NLS-21$ //$NON-NLS-22$ //$NON-NLS-23$ //$NON-NLS-24$ //$NON-NLS-25$ //$NON-NLS-26$ //$NON-NLS-27$ //$NON-NLS-28$ //$NON-NLS-29$
+ public static final String[] tests = new String[] {"testSimpleApp", "testInvalidArgs", "testAsyncValue01", "testAsyncValue02", "testAsyncValue03", "testAsyncValue04", "testAsyncValue05", "testAsyncValue06", "testExitValue01", "testExitValue02", "testExitValue03", "testExitValue04", "testExitValue05", "testExitValue06", "testExitValue07", "testExitValue08", "testExitValue09", "testExitValue10", "testGlobalSingleton", "testCardinality01", "testCardinality02", "testMainThreaded01", "testMainThreaded02", "testHandleEvents01", "testDescriptorEvents01", "testPersistentLock01", "testPersistentLock02", "testPersistentLock03", "testPersistentSchedule01", "testPersistentSchedule02", "testPersistentSchedule03", "testPersistentSchedule04", "testPersistentSchedule05", "testPersistentSchedule06", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$//$NON-NLS-6$//$NON-NLS-7$//$NON-NLS-8$//$NON-NLS-9$//$NON-NLS-10$//$NON-NLS-11$//$NON-NLS-12$//$NON-NLS-13$//$NON-NLS-14$//$NON-NLS-15$//$NON-NLS-16$//$NON-NLS-17$//$NON-NLS-18$//$NON-NLS-19$//$NON-NLS-20$//$NON-NLS-21$//$NON-NLS-22$//$NON-NLS-23$//$NON-NLS-24$//$NON-NLS-25$//$NON-NLS-26$//$NON-NLS-27$//$NON-NLS-28$//$NON-NLS-29$
+ "testPersistentSchedule07", "testPersistentSchedule08", "testFailedApplication01", "testDestroyBeforeStart01", "testDestroyBeforeStart02"};
private static final String PI_OSGI_SERVICES = "org.eclipse.osgi.services"; //$NON-NLS-1$
+ private static final String PI_OSGI_UTIL = "org.eclipse.osgi.util";
public static Test suite() {
TestSuite suite = new TestSuite(ApplicationAdminTest.class.getName());
@@ -42,6 +43,7 @@ public class ApplicationAdminTest extends OSGiTest {
String[] ids = ConfigurationSessionTestSuite.MINIMAL_BUNDLE_SET;
for (int i = 0; i < ids.length; i++)
appAdminSessionTest.addBundle(ids[i]);
+ appAdminSessionTest.addBundle(PI_OSGI_UTIL);
appAdminSessionTest.addBundle(PI_OSGI_SERVICES);
appAdminSessionTest.addBundle(PI_OSGI_TESTS);
appAdminSessionTest.setApplicationId(testRunnerApp);
diff --git a/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
index 96aac648f..7e7bf9de7 100644
--- a/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi.util/META-INF/MANIFEST.MF
@@ -2,18 +2,22 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %osgiUtil
Bundle-SymbolicName: org.eclipse.osgi.util
-Bundle-Version: 3.3.100.qualifier
+Bundle-Version: 3.4.0.qualifier
Bundle-Description: %osgiUtilDes
Bundle-Vendor: %eclipse.org
Bundle-Localization: plugin
Bundle-DocUrl: http://www.eclipse.org
Bundle-ContactAddress: www.eclipse.org
-Export-Package: org.osgi.util.measurement; version="1.0.1",
- org.osgi.util.position; version="1.0.1",
- org.osgi.util.xml; version="1.0.1"
+Export-Package: org.osgi.util.function;version="1.0",
+ org.osgi.util.measurement;version="1.0.1",
+ org.osgi.util.position;version="1.0.1";uses:="org.osgi.util.measurement",
+ org.osgi.util.promise;version="1.0";uses:="org.osgi.util.function",
+ org.osgi.util.xml;version="1.0.1";uses:="org.osgi.framework,javax.xml.parsers"
Import-Package: org.osgi.framework; version=1.1,
javax.xml.parsers,
- org.osgi.util.measurement; version="[1.0.1, 1.2)",
- org.osgi.util.position; version="[1.0.1, 1.2)",
- org.osgi.util.xml; version="[1.0.1, 1.2)"
+ org.osgi.util.function; version="[1.0, 1.1)",
+ org.osgi.util.measurement; version="[1.0.1, 1.1)",
+ org.osgi.util.position; version="[1.0.1, 1.1)",
+ org.osgi.util.promise; version="[1.0, 1.1)",
+ org.osgi.util.xml; version="[1.0.1, 1.1)"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/bundles/org.eclipse.osgi.util/build.properties b/bundles/org.eclipse.osgi.util/build.properties
index 3ead86b05..95558127f 100644
--- a/bundles/org.eclipse.osgi.util/build.properties
+++ b/bundles/org.eclipse.osgi.util/build.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2003, 2013 IBM Corporation and others.
+# Copyright (c) 2003, 2016 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -17,3 +17,4 @@ src.includes = about.html,\
about_files/
source.. = src/
output.. = bin/
+jars.extra.classpath = lib/osgi.annotation.jar
diff --git a/bundles/org.eclipse.osgi.util/lib/osgi.annotation.jar b/bundles/org.eclipse.osgi.util/lib/osgi.annotation.jar
new file mode 100644
index 000000000..dda27d2fe
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/lib/osgi.annotation.jar
Binary files differ
diff --git a/bundles/org.eclipse.osgi.util/pom.xml b/bundles/org.eclipse.osgi.util/pom.xml
index 3be91f5c1..c1b4a55fc 100644
--- a/bundles/org.eclipse.osgi.util/pom.xml
+++ b/bundles/org.eclipse.osgi.util/pom.xml
@@ -19,7 +19,7 @@
</parent>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.util</artifactId>
- <version>3.3.100-SNAPSHOT</version>
+ <version>3.4.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>
<plugins>
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Function.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Function.java
new file mode 100644
index 000000000..5d812f75c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Function.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.function;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A function that accepts a single argument and produces a result.
+ *
+ * <p>
+ * This is a functional interface and can be used as the assignment target for a
+ * lambda expression or method reference.
+ *
+ * @param <T> The type of the function input.
+ * @param <R> The type of the function output.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface Function<T, R> {
+ /**
+ * Applies this function to the specified argument.
+ *
+ * @param t The input to this function.
+ * @return The output of this function.
+ */
+ R apply(T t);
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Predicate.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Predicate.java
new file mode 100644
index 000000000..0c2c61f78
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/Predicate.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.function;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A predicate that accepts a single argument and produces a boolean result.
+ *
+ * <p>
+ * This is a functional interface and can be used as the assignment target for a
+ * lambda expression or method reference.
+ *
+ * @param <T> The type of the predicate input.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface Predicate<T> {
+ /**
+ * Evaluates this predicate on the specified argument.
+ *
+ * @param t The input to this predicate.
+ * @return {@code true} if the specified argument is accepted by this
+ * predicate; {@code false} otherwise.
+ */
+ boolean test(T t);
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/package-info.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/package-info.java
new file mode 100644
index 000000000..899d786b2
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Function Package Version 1.0.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.function; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.function; version="[1.0,1.1)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.0")
+package org.osgi.util.function;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/packageinfo b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/packageinfo
new file mode 100644
index 000000000..7c8de0324
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/function/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Deferred.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Deferred.java
new file mode 100644
index 000000000..e9ff0a6fa
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Deferred.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import static org.osgi.util.promise.PromiseImpl.requireNonNull;
+
+/**
+ * A Deferred Promise resolution.
+ *
+ * <p>
+ * Instances of this class can be used to create a {@link Promise} that can be
+ * resolved in the future. The {@link #getPromise() associated} Promise can be
+ * successfully resolved with {@link #resolve(Object)} or resolved with a
+ * failure with {@link #fail(Throwable)}. It can also be resolved with the
+ * resolution of another promise using {@link #resolveWith(Promise)}.
+ *
+ * <p>
+ * The associated Promise can be provided to any one, but the Deferred object
+ * should be made available only to the party that will responsible for
+ * resolving the Promise.
+ *
+ * @param <T> The value type associated with the created Promise.
+ *
+ * @Immutable
+ * @author $Id$
+ */
+public class Deferred<T> {
+ private final PromiseImpl<T> promise;
+
+ /**
+ * Create a new Deferred with an associated Promise.
+ */
+ public Deferred() {
+ promise = new PromiseImpl<T>();
+ }
+
+ /**
+ * Returns the Promise associated with this Deferred.
+ *
+ * @return The Promise associated with this Deferred.
+ */
+ public Promise<T> getPromise() {
+ return promise;
+ }
+
+ /**
+ * Successfully resolve the Promise associated with this Deferred.
+ *
+ * <p>
+ * After the associated Promise is resolved with the specified value, all
+ * registered {@link Promise#onResolve(Runnable) callbacks} are called and
+ * any {@link Promise#then(Success, Failure) chained} Promises are resolved.
+ *
+ * <p>
+ * Resolving the associated Promise <i>happens-before</i> any registered
+ * callback is called. That is, in a registered callback,
+ * {@link Promise#isDone()} must return {@code true} and
+ * {@link Promise#getValue()} and {@link Promise#getFailure()} must not
+ * block.
+ *
+ * @param value The value of the resolved Promise.
+ * @throws IllegalStateException If the associated Promise was already
+ * resolved.
+ */
+ public void resolve(T value) {
+ promise.resolve(value, null);
+ }
+
+ /**
+ * Fail the Promise associated with this Deferred.
+ *
+ * <p>
+ * After the associated Promise is resolved with the specified failure, all
+ * registered {@link Promise#onResolve(Runnable) callbacks} are called and
+ * any {@link Promise#then(Success, Failure) chained} Promises are resolved.
+ *
+ * <p>
+ * Resolving the associated Promise <i>happens-before</i> any registered
+ * callback is called. That is, in a registered callback,
+ * {@link Promise#isDone()} must return {@code true} and
+ * {@link Promise#getValue()} and {@link Promise#getFailure()} must not
+ * block.
+ *
+ * @param failure The failure of the resolved Promise. Must not be
+ * {@code null}.
+ * @throws IllegalStateException If the associated Promise was already
+ * resolved.
+ */
+ public void fail(Throwable failure) {
+ promise.resolve(null, requireNonNull(failure));
+ }
+
+ /**
+ * Resolve the Promise associated with this Deferred with the specified
+ * Promise.
+ *
+ * <p>
+ * If the specified Promise is successfully resolved, the associated Promise
+ * is resolved with the value of the specified Promise. If the specified
+ * Promise is resolved with a failure, the associated Promise is resolved
+ * with the failure of the specified Promise.
+ *
+ * <p>
+ * After the associated Promise is resolved with the specified Promise, all
+ * registered {@link Promise#onResolve(Runnable) callbacks} are called and
+ * any {@link Promise#then(Success, Failure) chained} Promises are resolved.
+ *
+ * <p>
+ * Resolving the associated Promise <i>happens-before</i> any registered
+ * callback is called. That is, in a registered callback,
+ * {@link Promise#isDone()} must return {@code true} and
+ * {@link Promise#getValue()} and {@link Promise#getFailure()} must not
+ * block.
+ *
+ * @param with A Promise whose value or failure must be used to resolve the
+ * associated Promise. Must not be {@code null}.
+ * @return A Promise that is resolved only when the associated Promise is
+ * resolved by the specified Promise. The returned Promise must be
+ * successfully resolved with the value {@code null}, if the
+ * associated Promise was resolved by the specified Promise. The
+ * returned Promise must be resolved with a failure of
+ * {@link IllegalStateException}, if the associated Promise was
+ * already resolved when the specified Promise was resolved.
+ */
+ public Promise<Void> resolveWith(Promise<? extends T> with) {
+ return promise.resolveWith(with);
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/FailedPromisesException.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/FailedPromisesException.java
new file mode 100644
index 000000000..95546abe5
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/FailedPromisesException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Promise failure exception for a collection of failed Promises.
+ *
+ * @author $Id$
+ */
+public class FailedPromisesException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private final Collection<Promise<?>> failed;
+
+ /**
+ * Create a new FailedPromisesException with the specified Promises.
+ *
+ * @param failed A collection of Promises that have been resolved with a
+ * failure. Must not be {@code null}, must not be empty and all of
+ * the elements in the collection must not be {@code null}.
+ * @param cause The cause of this exception. This is typically the failure
+ * of the first Promise in the specified collection.
+ */
+ public FailedPromisesException(Collection<Promise<?>> failed, Throwable cause) {
+ super(cause);
+ this.failed = Collections.unmodifiableCollection(failed);
+ }
+
+ /**
+ * Returns the collection of Promises that have been resolved with a
+ * failure.
+ *
+ * @return The collection of Promises that have been resolved with a
+ * failure. The returned collection is unmodifiable.
+ */
+ public Collection<Promise<?>> getFailedPromises() {
+ return failed;
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Failure.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Failure.java
new file mode 100644
index 000000000..4e6a17884
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Failure.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Failure callback for a Promise.
+ *
+ * <p>
+ * A Failure callback is registered with a {@link Promise} using the
+ * {@link Promise#then(Success, Failure)} method and is called if the Promise is
+ * resolved with a failure.
+ *
+ * <p>
+ * This is a functional interface and can be used as the assignment target for a
+ * lambda expression or method reference.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface Failure {
+ /**
+ * Failure callback for a Promise.
+ *
+ * <p>
+ * This method is called if the Promise with which it is registered resolves
+ * with a failure.
+ *
+ * <p>
+ * In the remainder of this description we will refer to the Promise
+ * returned by {@link Promise#then(Success, Failure)} when this Failure
+ * callback was registered as the chained Promise.
+ *
+ * <p>
+ * If this methods completes normally, the chained Promise must be failed
+ * with the same exception which failed the resolved Promise. If this method
+ * throws an exception, the chained Promise must be failed with the thrown
+ * exception.
+ *
+ * @param resolved The failed resolved {@link Promise}.
+ * @throws Exception The chained Promise must be failed with the thrown
+ * exception.
+ */
+ void fail(Promise<?> resolved) throws Exception;
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promise.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promise.java
new file mode 100644
index 000000000..ffa193393
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promise.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import java.lang.reflect.InvocationTargetException;
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.util.function.Function;
+import org.osgi.util.function.Predicate;
+
+/**
+ * A Promise of a value.
+ *
+ * <p>
+ * A Promise represents a future value. It handles the interactions for
+ * asynchronous processing. A {@link Deferred} object can be used to create a
+ * Promise and later resolve the Promise. A Promise is used by the caller of an
+ * asynchronous function to get the result or handle the error. The caller can
+ * either get a callback when the Promise is resolved with a value or an error,
+ * or the Promise can be used in chaining. In chaining, callbacks are provided
+ * that receive the resolved Promise, and a new Promise is generated that
+ * resolves based upon the result of a callback.
+ *
+ * <p>
+ * Both {@link #onResolve(Runnable) callbacks} and
+ * {@link #then(Success, Failure) chaining} can be repeated any number of times,
+ * even after the Promise has been resolved.
+ * <p>
+ * Example callback usage:
+ *
+ * <pre>
+ * final Promise&lt;String&gt; foo = foo();
+ * foo.onResolve(new Runnable() {
+ * public void run() {
+ * System.out.println(foo.getValue());
+ * }
+ * });
+ * </pre>
+ *
+ * Example chaining usage;
+ *
+ * <pre>
+ * Success&lt;String,String&gt; doubler = new Success&lt;String,String&gt;() {
+ * public Promise&lt;String&gt; call(Promise&lt;String&gt; p) throws Exception {
+ * return Promises.resolved(p.getValue()+p.getValue());
+ * }
+ * };
+ * final Promise&lt;String&gt; foo = foo().then(doubler).then(doubler);
+ * foo.onResolve(new Runnable() {
+ * public void run() {
+ * System.out.println(foo.getValue());
+ * }
+ * });
+ * </pre>
+ *
+ * @param <T> The value type associated with this Promise.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface Promise<T> {
+
+ /**
+ * Returns whether this Promise has been resolved.
+ *
+ * <p>
+ * This Promise may be successfully resolved or resolved with a failure.
+ *
+ * @return {@code true} if this Promise was resolved either successfully or
+ * with a failure; {@code false} if this Promise is unresolved.
+ */
+ boolean isDone();
+
+ /**
+ * Returns the value of this Promise.
+ *
+ * <p>
+ * If this Promise is not {@link #isDone() resolved}, this method must block
+ * and wait for this Promise to be resolved before completing.
+ *
+ * <p>
+ * If this Promise was successfully resolved, this method returns with the
+ * value of this Promise. If this Promise was resolved with a failure, this
+ * method must throw an {@code InvocationTargetException} with the
+ * {@link #getFailure() failure exception} as the cause.
+ *
+ * @return The value of this resolved Promise.
+ * @throws InvocationTargetException If this Promise was resolved with a
+ * failure. The cause of the {@code InvocationTargetException} is
+ * the failure exception.
+ * @throws InterruptedException If the current thread was interrupted while
+ * waiting.
+ */
+ T getValue() throws InvocationTargetException, InterruptedException;
+
+ /**
+ * Returns the failure of this Promise.
+ *
+ * <p>
+ * If this Promise is not {@link #isDone() resolved}, this method must block
+ * and wait for this Promise to be resolved before completing.
+ *
+ * <p>
+ * If this Promise was resolved with a failure, this method returns with the
+ * failure of this Promise. If this Promise was successfully resolved, this
+ * method must return {@code null}.
+ *
+ * @return The failure of this resolved Promise or {@code null} if this
+ * Promise was successfully resolved.
+ * @throws InterruptedException If the current thread was interrupted while
+ * waiting.
+ */
+ Throwable getFailure() throws InterruptedException;
+
+ /**
+ * Register a callback to be called when this Promise is resolved.
+ *
+ * <p>
+ * The specified callback is called when this Promise is resolved either
+ * successfully or with a failure.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * <p>
+ * Resolving this Promise <i>happens-before</i> any registered callback is
+ * called. That is, in a registered callback, {@link #isDone()} must return
+ * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
+ * block.
+ *
+ * <p>
+ * A callback may be called on a different thread than the thread which
+ * registered the callback. So the callback must be thread safe but can rely
+ * upon that the registration of the callback <i>happens-before</i> the
+ * registered callback is called.
+ *
+ * @param callback A callback to be called when this Promise is resolved.
+ * Must not be {@code null}.
+ * @return This Promise.
+ */
+ Promise<T> onResolve(Runnable callback);
+
+ /**
+ * Chain a new Promise to this Promise with Success and Failure callbacks.
+ *
+ * <p>
+ * The specified {@link Success} callback is called when this Promise is
+ * successfully resolved and the specified {@link Failure} callback is
+ * called when this Promise is resolved with a failure.
+ *
+ * <p>
+ * This method returns a new Promise which is chained to this Promise. The
+ * returned Promise must be resolved when this Promise is resolved after the
+ * specified Success or Failure callback is executed. The result of the
+ * executed callback must be used to resolve the returned Promise. Multiple
+ * calls to this method can be used to create a chain of promises which are
+ * resolved in sequence.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the Success callback is
+ * executed and the result Promise, if any, or thrown exception is used to
+ * resolve the returned Promise from this method. If this Promise is
+ * resolved with a failure, the Failure callback is executed and the
+ * returned Promise from this method is failed.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * <p>
+ * Resolving this Promise <i>happens-before</i> any registered callback is
+ * called. That is, in a registered callback, {@link #isDone()} must return
+ * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
+ * block.
+ *
+ * <p>
+ * A callback may be called on a different thread than the thread which
+ * registered the callback. So the callback must be thread safe but can rely
+ * upon that the registration of the callback <i>happens-before</i> the
+ * registered callback is called.
+ *
+ * @param <R> The value type associated with the returned Promise.
+ * @param success A Success callback to be called when this Promise is
+ * successfully resolved. May be {@code null} if no Success callback
+ * is required. In this case, the returned Promise must be resolved
+ * with the value {@code null} when this Promise is successfully
+ * resolved.
+ * @param failure A Failure callback to be called when this Promise is
+ * resolved with a failure. May be {@code null} if no Failure
+ * callback is required.
+ * @return A new Promise which is chained to this Promise. The returned
+ * Promise must be resolved when this Promise is resolved after the
+ * specified Success or Failure callback, if any, is executed.
+ */
+ <R> Promise<R> then(Success<? super T, ? extends R> success, Failure failure);
+
+ /**
+ * Chain a new Promise to this Promise with a Success callback.
+ *
+ * <p>
+ * This method performs the same function as calling
+ * {@link #then(Success, Failure)} with the specified Success callback and
+ * {@code null} for the Failure callback.
+ *
+ * @param <R> The value type associated with the returned Promise.
+ * @param success A Success callback to be called when this Promise is
+ * successfully resolved. May be {@code null} if no Success callback
+ * is required. In this case, the returned Promise must be resolved
+ * with the value {@code null} when this Promise is successfully
+ * resolved.
+ * @return A new Promise which is chained to this Promise. The returned
+ * Promise must be resolved when this Promise is resolved after the
+ * specified Success, if any, is executed.
+ * @see #then(Success, Failure)
+ */
+ <R> Promise<R> then(Success<? super T, ? extends R> success);
+
+ /**
+ * Filter the value of this Promise.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must
+ * either be resolved with the value of this Promise, if the specified
+ * Predicate accepts that value, or failed with a
+ * {@code NoSuchElementException}, if the specified Predicate does not
+ * accept that value. If the specified Predicate throws an exception, the
+ * returned Promise must be failed with the exception.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the returned Promise must be
+ * failed with that failure.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param predicate The Predicate to evaluate the value of this Promise.
+ * Must not be {@code null}.
+ * @return A Promise that filters the value of this Promise.
+ */
+ Promise<T> filter(Predicate<? super T> predicate);
+
+ /**
+ * Map the value of this Promise.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must be
+ * resolved with the value of specified Function as applied to the value of
+ * this Promise. If the specified Function throws an exception, the returned
+ * Promise must be failed with the exception.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the returned Promise must be
+ * failed with that failure.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param <R> The value type associated with the returned Promise.
+ * @param mapper The Function that must map the value of this Promise to the
+ * value that must be used to resolve the returned Promise. Must not
+ * be {@code null}.
+ * @return A Promise that returns the value of this Promise as mapped by the
+ * specified Function.
+ */
+ <R> Promise<R> map(Function<? super T, ? extends R> mapper);
+
+ /**
+ * FlatMap the value of this Promise.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must be
+ * resolved with the Promise from the specified Function as applied to the
+ * value of this Promise. If the specified Function throws an exception, the
+ * returned Promise must be failed with the exception.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the returned Promise must be
+ * failed with that failure.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param <R> The value type associated with the returned Promise.
+ * @param mapper The Function that must flatMap the value of this Promise to
+ * a Promise that must be used to resolve the returned Promise. Must
+ * not be {@code null}.
+ * @return A Promise that returns the value of this Promise as mapped by the
+ * specified Function.
+ */
+ <R> Promise<R> flatMap(Function<? super T, Promise<? extends R>> mapper);
+
+ /**
+ * Recover from a failure of this Promise with a recovery value.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must be
+ * resolved with the value of this Promise.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the specified Function is
+ * applied to this Promise to produce a recovery value.
+ * <ul>
+ * <li>If the recovery value is not {@code null}, the returned Promise must
+ * be resolved with the recovery value.</li>
+ * <li>If the recovery value is {@code null}, the returned Promise must be
+ * failed with the failure of this Promise.</li>
+ * <li>If the specified Function throws an exception, the returned Promise
+ * must be failed with that exception.</li>
+ * </ul>
+ *
+ * <p>
+ * To recover from a failure of this Promise with a recovery value of
+ * {@code null}, the {@link #recoverWith(Function)} method must be used. The
+ * specified Function for {@link #recoverWith(Function)} can return
+ * {@code Promises.resolved(null)} to supply the desired {@code null} value.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param recovery If this Promise resolves with a failure, the specified
+ * Function is called to produce a recovery value to be used to
+ * resolve the returned Promise. Must not be {@code null}.
+ * @return A Promise that resolves with the value of this Promise or
+ * recovers from the failure of this Promise.
+ */
+ Promise<T> recover(Function<Promise<?>, ? extends T> recovery);
+
+ /**
+ * Recover from a failure of this Promise with a recovery Promise.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must be
+ * resolved with the value of this Promise.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the specified Function is
+ * applied to this Promise to produce a recovery Promise.
+ * <ul>
+ * <li>If the recovery Promise is not {@code null}, the returned Promise
+ * must be resolved with the recovery Promise.</li>
+ * <li>If the recovery Promise is {@code null}, the returned Promise must be
+ * failed with the failure of this Promise.</li>
+ * <li>If the specified Function throws an exception, the returned Promise
+ * must be failed with that exception.</li>
+ * </ul>
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param recovery If this Promise resolves with a failure, the specified
+ * Function is called to produce a recovery Promise to be used to
+ * resolve the returned Promise. Must not be {@code null}.
+ * @return A Promise that resolves with the value of this Promise or
+ * recovers from the failure of this Promise.
+ */
+ Promise<T> recoverWith(Function<Promise<?>, Promise<? extends T>> recovery);
+
+ /**
+ * Fall back to the value of the specified Promise if this Promise fails.
+ *
+ * <p>
+ * If this Promise is successfully resolved, the returned Promise must be
+ * resolved with the value of this Promise.
+ *
+ * <p>
+ * If this Promise is resolved with a failure, the successful result of the
+ * specified Promise is used to resolve the returned Promise. If the
+ * specified Promise is resolved with a failure, the returned Promise must
+ * be failed with the failure of this Promise rather than the failure of the
+ * specified Promise.
+ *
+ * <p>
+ * This method may be called at any time including before and after this
+ * Promise has been resolved.
+ *
+ * @param fallback The Promise whose value must be used to resolve the
+ * returned Promise if this Promise resolves with a failure. Must not
+ * be {@code null}.
+ * @return A Promise that returns the value of this Promise or falls back to
+ * the value of the specified Promise.
+ */
+ Promise<T> fallbackTo(Promise<? extends T> fallback);
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/PromiseImpl.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/PromiseImpl.java
new file mode 100644
index 000000000..ca2be5e80
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/PromiseImpl.java
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import org.osgi.util.function.Function;
+import org.osgi.util.function.Predicate;
+
+/**
+ * Promise implementation.
+ *
+ * <p>
+ * This class is not used directly by clients. Clients should use
+ * {@link Deferred} to create a resolvable {@link Promise}.
+ *
+ * @param <T> The result type associated with the Promise.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+final class PromiseImpl<T> implements Promise<T> {
+ /**
+ * A ConcurrentLinkedQueue to hold the callbacks for this Promise, so no
+ * additional synchronization is required to write to or read from the
+ * queue.
+ */
+ private final ConcurrentLinkedQueue<Runnable> callbacks;
+ /**
+ * A CountDownLatch to manage the resolved state of this Promise.
+ *
+ * <p>
+ * This object is used as the synchronizing object to provide a critical
+ * section in {@link #resolve(Object, Throwable)} so that only a single
+ * thread can write the resolved state variables and open the latch.
+ *
+ * <p>
+ * The resolved state variables, {@link #value} and {@link #fail}, must only
+ * be written when the latch is closed (getCount() != 0) and must only be
+ * read when the latch is open (getCount() == 0). The latch state must
+ * always be checked before writing or reading since the resolved state
+ * variables' memory consistency is guarded by the latch.
+ */
+ private final CountDownLatch resolved;
+ /**
+ * The value of this Promise if successfully resolved.
+ *
+ * @GuardedBy("resolved")
+ * @see #resolved
+ */
+ private T value;
+ /**
+ * The failure of this Promise if resolved with a failure or {@code null} if
+ * successfully resolved.
+ *
+ * @GuardedBy("resolved")
+ * @see #resolved
+ */
+ private Throwable fail;
+
+ /**
+ * Initialize this Promise.
+ */
+ PromiseImpl() {
+ callbacks = new ConcurrentLinkedQueue<Runnable>();
+ resolved = new CountDownLatch(1);
+ }
+
+ /**
+ * Initialize and resolve this Promise.
+ *
+ * @param v The value of this resolved Promise.
+ * @param f The failure of this resolved Promise.
+ */
+ PromiseImpl(T v, Throwable f) {
+ value = v;
+ fail = f;
+ callbacks = new ConcurrentLinkedQueue<Runnable>();
+ resolved = new CountDownLatch(0);
+ }
+
+ /**
+ * Resolve this Promise.
+ *
+ * @param v The value of this Promise.
+ * @param f The failure of this Promise.
+ */
+ void resolve(T v, Throwable f) {
+ // critical section: only one resolver at a time
+ synchronized (resolved) {
+ if (resolved.getCount() == 0) {
+ throw new IllegalStateException("Already resolved");
+ }
+ /*
+ * The resolved state variables must be set before opening the
+ * latch. This safely publishes them to be read by other threads
+ * that must verify the latch is open before reading.
+ */
+ value = v;
+ fail = f;
+ resolved.countDown();
+ }
+ notifyCallbacks(); // call any registered callbacks
+ }
+
+ /**
+ * Call any registered callbacks if this Promise is resolved.
+ */
+ private void notifyCallbacks() {
+ if (resolved.getCount() != 0) {
+ return; // return if not resolved
+ }
+
+ /*
+ * Note: multiple threads can be in this method removing callbacks from
+ * the queue and calling them, so the order in which callbacks are
+ * called cannot be specified.
+ */
+ for (Runnable callback = callbacks.poll(); callback != null; callback = callbacks.poll()) {
+ try {
+ callback.run();
+ } catch (Throwable t) {
+ Logger.logCallbackException(t);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDone() {
+ return resolved.getCount() == 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public T getValue() throws InvocationTargetException, InterruptedException {
+ resolved.await();
+ if (fail == null) {
+ return value;
+ }
+ throw new InvocationTargetException(fail);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Throwable getFailure() throws InterruptedException {
+ resolved.await();
+ return fail;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Promise<T> onResolve(Runnable callback) {
+ callbacks.offer(callback);
+ notifyCallbacks(); // call any registered callbacks
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <R> Promise<R> then(Success<? super T, ? extends R> success, Failure failure) {
+ PromiseImpl<R> chained = new PromiseImpl<R>();
+ onResolve(new Then<R>(chained, success, failure));
+ return chained;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <R> Promise<R> then(Success<? super T, ? extends R> success) {
+ return then(success, null);
+ }
+
+ /**
+ * A callback used to chain promises for the {@link #then(Success, Failure)}
+ * method.
+ *
+ * @Immutable
+ */
+ private final class Then<R> implements Runnable {
+ private final PromiseImpl<R> chained;
+ private final Success<T, ? extends R> success;
+ private final Failure failure;
+
+ @SuppressWarnings("unchecked")
+ Then(PromiseImpl<R> chained, Success<? super T, ? extends R> success, Failure failure) {
+ this.chained = chained;
+ this.success = (Success<T, ? extends R>) success;
+ this.failure = failure;
+ }
+
+ public void run() {
+ Throwable f;
+ final boolean interrupted = Thread.interrupted();
+ try {
+ f = getFailure();
+ } catch (Throwable e) {
+ f = e; // propagate new exception
+ } finally {
+ if (interrupted) { // restore interrupt status
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (f != null) {
+ if (failure != null) {
+ try {
+ failure.fail(PromiseImpl.this);
+ } catch (Throwable e) {
+ f = e; // propagate new exception
+ }
+ }
+ // fail chained
+ chained.resolve(null, f);
+ return;
+ }
+ Promise<? extends R> returned = null;
+ if (success != null) {
+ try {
+ returned = success.call(PromiseImpl.this);
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ }
+ if (returned == null) {
+ // resolve chained with null value
+ chained.resolve(null, null);
+ } else {
+ // resolve chained when returned promise is resolved
+ returned.onResolve(new Chain<R>(chained, returned));
+ }
+ }
+ }
+
+ /**
+ * A callback used to resolve the chained Promise when the Promise promise
+ * is resolved.
+ *
+ * @Immutable
+ */
+ private final static class Chain<R> implements Runnable {
+ private final PromiseImpl<R> chained;
+ private final Promise<? extends R> promise;
+ private final Throwable failure;
+
+ Chain(PromiseImpl<R> chained, Promise<? extends R> promise) {
+ this.chained = chained;
+ this.promise = promise;
+ this.failure = null;
+ }
+
+ Chain(PromiseImpl<R> chained, Promise<? extends R> promise, Throwable failure) {
+ this.chained = chained;
+ this.promise = promise;
+ this.failure = failure;
+ }
+
+ public void run() {
+ R value = null;
+ Throwable f;
+ final boolean interrupted = Thread.interrupted();
+ try {
+ f = promise.getFailure();
+ if (f == null) {
+ value = promise.getValue();
+ } else if (failure != null) {
+ f = failure;
+ }
+ } catch (Throwable e) {
+ f = e; // propagate new exception
+ } finally {
+ if (interrupted) { // restore interrupt status
+ Thread.currentThread().interrupt();
+ }
+ }
+ chained.resolve(value, f);
+ }
+ }
+
+ /**
+ * Resolve this Promise with the specified Promise.
+ *
+ * <p>
+ * If the specified Promise is successfully resolved, this Promise is
+ * resolved with the value of the specified Promise. If the specified
+ * Promise is resolved with a failure, this Promise is resolved with the
+ * failure of the specified Promise.
+ *
+ * @param with A Promise whose value or failure must be used to resolve this
+ * Promise. Must not be {@code null}.
+ * @return A Promise that is resolved only when this Promise is resolved by
+ * the specified Promise. The returned Promise must be successfully
+ * resolved with the value {@code null}, if this Promise was
+ * resolved by the specified Promise. The returned Promise must be
+ * resolved with a failure of {@link IllegalStateException}, if this
+ * Promise was already resolved when the specified Promise was
+ * resolved.
+ */
+ Promise<Void> resolveWith(Promise<? extends T> with) {
+ PromiseImpl<Void> chained = new PromiseImpl<Void>();
+ ResolveWith resolveWith = new ResolveWith(chained);
+ with.then(resolveWith, resolveWith);
+ return chained;
+ }
+
+ /**
+ * A callback used to resolve this Promise with another Promise for the
+ * {@link PromiseImpl#resolveWith(Promise)} method.
+ *
+ * @Immutable
+ */
+ private final class ResolveWith implements Success<T, Void>, Failure {
+ private final PromiseImpl<Void> chained;
+
+ ResolveWith(PromiseImpl<Void> chained) {
+ this.chained = chained;
+ }
+
+ public Promise<Void> call(Promise<T> with) throws Exception {
+ try {
+ resolve(with.getValue(), null);
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return null;
+ }
+ chained.resolve(null, null);
+ return null;
+ }
+
+ public void fail(Promise<?> with) throws Exception {
+ try {
+ resolve(null, with.getFailure());
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ chained.resolve(null, null);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Promise<T> filter(Predicate<? super T> predicate) {
+ return then(new Filter<T>(predicate));
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#filter(Predicate)} method.
+ *
+ * @Immutable
+ */
+ private static final class Filter<T> implements Success<T, T> {
+ private final Predicate<? super T> predicate;
+
+ Filter(Predicate<? super T> predicate) {
+ this.predicate = requireNonNull(predicate);
+ }
+
+ public Promise<T> call(Promise<T> resolved) throws Exception {
+ if (predicate.test(resolved.getValue())) {
+ return resolved;
+ }
+ throw new NoSuchElementException();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <R> Promise<R> map(Function<? super T, ? extends R> mapper) {
+ return then(new Map<T, R>(mapper));
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#map(Function)} method.
+ *
+ * @Immutable
+ */
+ private static final class Map<T, R> implements Success<T, R> {
+ private final Function<? super T, ? extends R> mapper;
+
+ Map(Function<? super T, ? extends R> mapper) {
+ this.mapper = requireNonNull(mapper);
+ }
+
+ public Promise<R> call(Promise<T> resolved) throws Exception {
+ return new PromiseImpl<R>(mapper.apply(resolved.getValue()), null);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <R> Promise<R> flatMap(Function<? super T, Promise<? extends R>> mapper) {
+ return then(new FlatMap<T, R>(mapper));
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#flatMap(Function)} method.
+ *
+ * @Immutable
+ */
+ private static final class FlatMap<T, R> implements Success<T, R> {
+ private final Function<? super T, Promise<? extends R>> mapper;
+
+ FlatMap(Function<? super T, Promise<? extends R>> mapper) {
+ this.mapper = requireNonNull(mapper);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Promise<R> call(Promise<T> resolved) throws Exception {
+ return (Promise<R>) mapper.apply(resolved.getValue());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Promise<T> recover(Function<Promise<?>, ? extends T> recovery) {
+ PromiseImpl<T> chained = new PromiseImpl<T>();
+ Recover<T> recover = new Recover<T>(chained, recovery);
+ then(recover, recover);
+ return chained;
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#recover(Function)} method.
+ *
+ * @Immutable
+ */
+ private static final class Recover<T> implements Success<T, Void>, Failure {
+ private final PromiseImpl<T> chained;
+ private final Function<Promise<?>, ? extends T> recovery;
+
+ Recover(PromiseImpl<T> chained, Function<Promise<?>, ? extends T> recovery) {
+ this.chained = chained;
+ this.recovery = requireNonNull(recovery);
+ }
+
+ public Promise<Void> call(Promise<T> resolved) throws Exception {
+ T value;
+ try {
+ value = resolved.getValue();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return null;
+ }
+ chained.resolve(value, null);
+ return null;
+ }
+
+ public void fail(Promise<?> resolved) throws Exception {
+ T recovered;
+ Throwable failure;
+ try {
+ recovered = recovery.apply(resolved);
+ failure = resolved.getFailure();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ if (recovered == null) {
+ chained.resolve(null, failure);
+ } else {
+ chained.resolve(recovered, null);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Promise<T> recoverWith(Function<Promise<?>, Promise<? extends T>> recovery) {
+ PromiseImpl<T> chained = new PromiseImpl<T>();
+ RecoverWith<T> recoverWith = new RecoverWith<T>(chained, recovery);
+ then(recoverWith, recoverWith);
+ return chained;
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#recoverWith(Function)} method.
+ *
+ * @Immutable
+ */
+ private static final class RecoverWith<T> implements Success<T, Void>, Failure {
+ private final PromiseImpl<T> chained;
+ private final Function<Promise<?>, Promise<? extends T>> recovery;
+
+ RecoverWith(PromiseImpl<T> chained, Function<Promise<?>, Promise<? extends T>> recovery) {
+ this.chained = chained;
+ this.recovery = requireNonNull(recovery);
+ }
+
+ public Promise<Void> call(Promise<T> resolved) throws Exception {
+ T value;
+ try {
+ value = resolved.getValue();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return null;
+ }
+ chained.resolve(value, null);
+ return null;
+ }
+
+ public void fail(Promise<?> resolved) throws Exception {
+ Promise<? extends T> recovered;
+ Throwable failure;
+ try {
+ recovered = recovery.apply(resolved);
+ failure = resolved.getFailure();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ if (recovered == null) {
+ chained.resolve(null, failure);
+ } else {
+ recovered.onResolve(new Chain<T>(chained, recovered));
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Promise<T> fallbackTo(Promise<? extends T> fallback) {
+ PromiseImpl<T> chained = new PromiseImpl<T>();
+ FallbackTo<T> fallbackTo = new FallbackTo<T>(chained, fallback);
+ then(fallbackTo, fallbackTo);
+ return chained;
+ }
+
+ /**
+ * A callback used by the {@link PromiseImpl#fallbackTo(Promise)} method.
+ *
+ * @Immutable
+ */
+ private static final class FallbackTo<T> implements Success<T, Void>, Failure {
+ private final PromiseImpl<T> chained;
+ private final Promise<? extends T> fallback;
+
+ FallbackTo(PromiseImpl<T> chained, Promise<? extends T> fallback) {
+ this.chained = chained;
+ this.fallback = requireNonNull(fallback);
+ }
+
+ public Promise<Void> call(Promise<T> resolved) throws Exception {
+ T value;
+ try {
+ value = resolved.getValue();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return null;
+ }
+ chained.resolve(value, null);
+ return null;
+ }
+
+ public void fail(Promise<?> resolved) throws Exception {
+ Throwable failure;
+ try {
+ failure = resolved.getFailure();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ fallback.onResolve(new Chain<T>(chained, fallback, failure));
+ }
+ }
+
+ static <V> V requireNonNull(V value) {
+ if (value != null) {
+ return value;
+ }
+ throw new NullPointerException();
+ }
+
+ /**
+ * Use the lazy initialization holder class idiom to delay creating a Logger
+ * until we actually need it.
+ */
+ private static final class Logger {
+ private final static java.util.logging.Logger LOGGER;
+ static {
+ LOGGER = java.util.logging.Logger.getLogger(PromiseImpl.class.getName());
+ }
+
+ static void logCallbackException(Throwable t) {
+ LOGGER.log(java.util.logging.Level.WARNING, "Exception from Promise callback", t);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java
new file mode 100644
index 000000000..06d506675
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import static org.osgi.util.promise.PromiseImpl.requireNonNull;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Static helper methods for {@link Promise}s.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+public class Promises {
+ private Promises() {
+ // disallow object creation
+ }
+
+ /**
+ * Create a new Promise that has been resolved with the specified value.
+ *
+ * @param <T> The value type associated with the returned Promise.
+ * @param value The value of the resolved Promise.
+ * @return A new Promise that has been resolved with the specified value.
+ */
+ public static <T> Promise<T> resolved(T value) {
+ return new PromiseImpl<T>(value, null);
+ }
+
+ /**
+ * Create a new Promise that has been resolved with the specified failure.
+ *
+ * @param <T> The value type associated with the returned Promise.
+ * @param failure The failure of the resolved Promise. Must not be
+ * {@code null}.
+ * @return A new Promise that has been resolved with the specified failure.
+ */
+ public static <T> Promise<T> failed(Throwable failure) {
+ return new PromiseImpl<T>(null, requireNonNull(failure));
+ }
+
+ /**
+ * Create a new Promise that is a latch on the resolution of the specified
+ * Promises.
+ *
+ * <p>
+ * The new Promise acts as a gate and must be resolved after all of the
+ * specified Promises are resolved.
+ *
+ * @param <T> The value type of the List value associated with the returned
+ * Promise.
+ * @param <S> A subtype of the value type of the List value associated with
+ * the returned Promise.
+ * @param promises The Promises which must be resolved before the returned
+ * Promise must be resolved. Must not be {@code null} and all of the
+ * elements in the collection must not be {@code null}.
+ * @return A Promise that is resolved only when all the specified Promises
+ * are resolved. The returned Promise must be successfully resolved
+ * with a List of the values in the order of the specified Promises
+ * if all the specified Promises are successfully resolved. The List
+ * in the returned Promise is the property of the caller and is
+ * modifiable. The returned Promise must be resolved with a failure
+ * of {@link FailedPromisesException} if any of the specified
+ * Promises are resolved with a failure. The failure
+ * {@link FailedPromisesException} must contain all of the specified
+ * Promises which resolved with a failure.
+ */
+ public static <T, S extends T> Promise<List<T>> all(Collection<Promise<S>> promises) {
+ if (promises.isEmpty()) {
+ List<T> result = new ArrayList<T>();
+ return resolved(result);
+ }
+ /* make a copy and capture the ordering */
+ List<Promise<? extends T>> list = new ArrayList<Promise<? extends T>>(promises);
+ PromiseImpl<List<T>> chained = new PromiseImpl<List<T>>();
+ All<T> all = new All<T>(chained, list);
+ for (Promise<? extends T> promise : list) {
+ promise.onResolve(all);
+ }
+ return chained;
+ }
+
+ /**
+ * Create a new Promise that is a latch on the resolution of the specified
+ * Promises.
+ *
+ * <p>
+ * The new Promise acts as a gate and must be resolved after all of the
+ * specified Promises are resolved.
+ *
+ * @param <T> The value type associated with the specified Promises.
+ * @param promises The Promises which must be resolved before the returned
+ * Promise must be resolved. Must not be {@code null} and all of the
+ * arguments must not be {@code null}.
+ * @return A Promise that is resolved only when all the specified Promises
+ * are resolved. The returned Promise must be successfully resolved
+ * with a List of the values in the order of the specified Promises
+ * if all the specified Promises are successfully resolved. The List
+ * in the returned Promise is the property of the caller and is
+ * modifiable. The returned Promise must be resolved with a failure
+ * of {@link FailedPromisesException} if any of the specified
+ * Promises are resolved with a failure. The failure
+ * {@link FailedPromisesException} must contain all of the specified
+ * Promises which resolved with a failure.
+ */
+ public static <T> Promise<List<T>> all(Promise<? extends T>... promises) {
+ @SuppressWarnings("unchecked")
+ List<Promise<T>> list = Arrays.asList((Promise<T>[]) promises);
+ return all(list);
+ }
+
+ /**
+ * A callback used to resolve a Promise when the specified list of Promises
+ * are resolved for the {@link Promises#all(Collection)} method.
+ *
+ * @ThreadSafe
+ */
+ private static final class All<T> implements Runnable {
+ private final PromiseImpl<List<T>> chained;
+ private final List<Promise<? extends T>> promises;
+ private final AtomicInteger promiseCount;
+
+ All(PromiseImpl<List<T>> chained, List<Promise<? extends T>> promises) {
+ this.chained = chained;
+ this.promises = promises;
+ this.promiseCount = new AtomicInteger(promises.size());
+ }
+
+ public void run() {
+ if (promiseCount.decrementAndGet() != 0) {
+ return;
+ }
+ List<T> result = new ArrayList<T>(promises.size());
+ List<Promise<?>> failed = new ArrayList<Promise<?>>(promises.size());
+ Throwable cause = null;
+ for (Promise<? extends T> promise : promises) {
+ Throwable failure;
+ T value;
+ try {
+ failure = promise.getFailure();
+ value = (failure != null) ? null : promise.getValue();
+ } catch (Throwable e) {
+ chained.resolve(null, e);
+ return;
+ }
+ if (failure != null) {
+ failed.add(promise);
+ if (cause == null) {
+ cause = failure;
+ }
+ } else {
+ result.add(value);
+ }
+ }
+ if (failed.isEmpty()) {
+ chained.resolve(result, null);
+ } else {
+ chained.resolve(null, new FailedPromisesException(failed, cause));
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Success.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Success.java
new file mode 100644
index 000000000..c29fc4fb6
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Success.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.util.promise;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Success callback for a Promise.
+ *
+ * <p>
+ * A Success callback is registered with a {@link Promise} using the
+ * {@link Promise#then(Success)} method and is called if the Promise is resolved
+ * successfully.
+ *
+ * <p>
+ * This is a functional interface and can be used as the assignment target for a
+ * lambda expression or method reference.
+ *
+ * @param <T> The value type of the resolved Promise passed as input to this
+ * callback.
+ * @param <R> The value type of the returned Promise from this callback.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ConsumerType
+public interface Success<T, R> {
+ /**
+ * Success callback for a Promise.
+ *
+ * <p>
+ * This method is called if the Promise with which it is registered resolves
+ * successfully.
+ *
+ * <p>
+ * In the remainder of this description we will refer to the Promise
+ * returned by this method as the returned Promise and the Promise returned
+ * by {@link Promise#then(Success)} when this Success callback was
+ * registered as the chained Promise.
+ *
+ * <p>
+ * If the returned Promise is {@code null} then the chained Promise must
+ * resolve immediately with a successful value of {@code null}. If the
+ * returned Promise is not {@code null} then the chained Promise must be
+ * resolved when the returned Promise is resolved.
+ *
+ * @param resolved The successfully resolved {@link Promise}.
+ * @return The Promise to use to resolve the chained Promise, or
+ * {@code null} if the chained Promise is to be resolved immediately
+ * with the value {@code null}.
+ * @throws Exception The chained Promise must be failed with the thrown
+ * exception.
+ */
+ Promise<R> call(Promise<T> resolved) throws Exception;
+}
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/package-info.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/package-info.java
new file mode 100644
index 000000000..5a3ec65d3
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Promise Package Version 1.0.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.promise; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.promise; version="[1.0,1.1)"}
+ *
+ * @author $Id$
+ */
+
+@Version("1.0")
+package org.osgi.util.promise;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/packageinfo b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/packageinfo
new file mode 100644
index 000000000..7c8de0324
--- /dev/null
+++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index 00cb55822..0f7985ae0 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -2,14 +2,22 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.runtime",
org.eclipse.core.runtime.internal.adaptor;x-internal:=true,
- org.eclipse.equinox.log;version="1.0",
- org.eclipse.osgi.container;version="1.2",
- org.eclipse.osgi.container.builders;version="1.0",
- org.eclipse.osgi.container.namespaces;version="1.0",
- org.eclipse.osgi.framework.console;version="1.1",
+ org.eclipse.equinox.log;version="1.0";uses:="org.osgi.framework,org.osgi.service.log",
+ org.eclipse.osgi.container;version="1.2";
+ uses:="org.eclipse.osgi.report.resolution,
+ org.osgi.framework.wiring,
+ org.osgi.framework.startlevel,
+ org.osgi.framework,
+ org.osgi.framework.hooks.resolver,
+ org.osgi.service.resolver,
+ org.osgi.resource,
+ org.eclipse.osgi.service.debug",
+ org.eclipse.osgi.container.builders;version="1.0";uses:="org.eclipse.osgi.util,org.eclipse.osgi.container",
+ org.eclipse.osgi.container.namespaces;version="1.0";uses:="org.osgi.resource",
+ org.eclipse.osgi.framework.console;version="1.1";uses:="org.osgi.framework",
org.eclipse.osgi.framework.eventmgr;version="1.2",
org.eclipse.osgi.framework.internal.reliablefile;x-internal:=true,
- org.eclipse.osgi.framework.log;version="1.1",
+ org.eclipse.osgi.framework.log;version="1.1";uses:="org.osgi.framework",
org.eclipse.osgi.framework.util;x-internal:=true,
org.eclipse.osgi.internal.debug;x-internal:=true,
org.eclipse.osgi.internal.framework;x-internal:=true,
@@ -26,18 +34,18 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru
org.eclipse.osgi.internal.serviceregistry;x-internal:=true,
org.eclipse.osgi.internal.signedcontent;x-internal:=true,
org.eclipse.osgi.internal.url;x-internal:=true,
- org.eclipse.osgi.launch;version="1.0",
- org.eclipse.osgi.report.resolution;version="1.0",
+ org.eclipse.osgi.launch;version="1.0";uses:="org.osgi.framework,org.osgi.framework.launch",
+ org.eclipse.osgi.report.resolution;version="1.0";uses:="org.osgi.service.resolver,org.osgi.resource",
org.eclipse.osgi.service.datalocation;version="1.3",
org.eclipse.osgi.service.debug;version="1.2",
org.eclipse.osgi.service.environment;version="1.3",
- org.eclipse.osgi.service.localization;version="1.1",
+ org.eclipse.osgi.service.localization;version="1.1";uses:="org.osgi.framework",
org.eclipse.osgi.service.pluginconversion;version="1.0",
- org.eclipse.osgi.service.resolver;version="1.6",
+ org.eclipse.osgi.service.resolver;version="1.6";uses:="org.osgi.framework,org.osgi.framework.hooks.resolver,org.osgi.framework.wiring",
org.eclipse.osgi.service.runnable;version="1.1",
org.eclipse.osgi.service.security;version="1.0",
org.eclipse.osgi.service.urlconversion;version="1.0",
- org.eclipse.osgi.signedcontent;version="1.0",
+ org.eclipse.osgi.signedcontent;version="1.0";uses:="org.osgi.framework",
org.eclipse.osgi.storage;x-friends:="org.eclipse.osgi.tests",
org.eclipse.osgi.storage.bundlefile;x-internal:=true,
org.eclipse.osgi.storage.url.reference;x-internal:=true,
@@ -45,27 +53,27 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru
org.eclipse.osgi.util;version="1.1",
org.osgi.dto;version="1.0",
org.osgi.framework;version="1.8",
- org.osgi.framework.dto;version="1.8",
- org.osgi.framework.hooks.bundle;version="1.1",
- org.osgi.framework.hooks.resolver;version="1.0",
- org.osgi.framework.hooks.service;version="1.1",
- org.osgi.framework.hooks.weaving;version="1.1",
- org.osgi.framework.launch;version="1.2",
- org.osgi.framework.namespace;version="1.1",
- org.osgi.framework.startlevel;version="1.0",
- org.osgi.framework.startlevel.dto;version="1.0",
- org.osgi.framework.wiring;version="1.2",
- org.osgi.framework.wiring.dto;version="1.2",
+ org.osgi.framework.dto;version="1.8";uses:="org.osgi.dto",
+ org.osgi.framework.hooks.bundle;version="1.1";uses:="org.osgi.framework",
+ org.osgi.framework.hooks.resolver;version="1.0";uses:="org.osgi.framework.wiring",
+ org.osgi.framework.hooks.service;version="1.1";uses:="org.osgi.framework",
+ org.osgi.framework.hooks.weaving;version="1.1";uses:="org.osgi.framework.wiring",
+ org.osgi.framework.launch;version="1.2";uses:="org.osgi.framework",
+ org.osgi.framework.namespace;version="1.1";uses:="org.osgi.resource",
+ org.osgi.framework.startlevel;version="1.0";uses:="org.osgi.framework",
+ org.osgi.framework.startlevel.dto;version="1.0";uses:="org.osgi.dto",
+ org.osgi.framework.wiring;version="1.2";uses:="org.osgi.framework,org.osgi.resource",
+ org.osgi.framework.wiring.dto;version="1.2";uses:="org.osgi.dto,org.osgi.resource.dto",
org.osgi.resource;version="1.0",
- org.osgi.resource.dto;version="1.0",
- org.osgi.service.condpermadmin;version="1.1.1",
- org.osgi.service.log;version="1.3",
- org.osgi.service.packageadmin;version="1.2",
+ org.osgi.resource.dto;version="1.0";uses:="org.osgi.dto",
+ org.osgi.service.condpermadmin;version="1.1.1";uses:="org.osgi.framework",
+ org.osgi.service.log;version="1.3";uses:="org.osgi.framework",
+ org.osgi.service.packageadmin;version="1.2";uses:="org.osgi.framework",
org.osgi.service.permissionadmin;version="1.2",
- org.osgi.service.resolver;version="1.0.1",
- org.osgi.service.startlevel;version="1.1",
+ org.osgi.service.resolver;version="1.0.1";uses:="org.osgi.resource",
+ org.osgi.service.startlevel;version="1.1";uses:="org.osgi.framework",
org.osgi.service.url;version="1.0",
- org.osgi.util.tracker;version="1.5.1"
+ org.osgi.util.tracker;version="1.5.1";uses:="org.osgi.framework"
Export-Service: org.osgi.service.packageadmin.PackageAdmin,
org.osgi.service.permissionadmin.PermissionAdmin,
org.osgi.service.startlevel.StartLevel,

Back to the top