Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBJ Hargrave2013-05-16 19:33:56 +0000
committerBJ Hargrave2013-05-22 20:57:48 +0000
commit9de0794924fc96e99cf4c0d90a29d9c7830200f0 (patch)
treed6618bf19a2586fd3b215d5131fde0b90d152143 /bundles/org.eclipse.osgi/osgi/src/org
parentda591a101c0a8a9ba0f8077143998aaebec887ed (diff)
downloadrt.equinox.framework-9de0794924fc96e99cf4c0d90a29d9c7830200f0.tar.gz
rt.equinox.framework-9de0794924fc96e99cf4c0d90a29d9c7830200f0.tar.xz
rt.equinox.framework-9de0794924fc96e99cf4c0d90a29d9c7830200f0.zip
RFC 195: Update OSGi API for prototype services
Signed-off-by: BJ Hargrave <hargrave@us.ibm.com>
Diffstat (limited to 'bundles/org.eclipse.osgi/osgi/src/org')
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java4
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundleContext.java141
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java47
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PrototypeServiceFactory.java124
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java43
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceObjects.java140
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java1
7 files changed, 434 insertions, 66 deletions
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java
index 5ebb357f8..a895c22e8 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java
@@ -761,8 +761,8 @@ public interface Bundle extends Comparable<Bundle> {
/**
* Returns this bundle's {@code ServiceReference} list for all services it
* is using or returns {@code null} if this bundle is not using any
- * services. A bundle is considered to be using a service if its use count
- * for that service is greater than zero.
+ * services. A bundle is considered to be using a service if it has any
+ * unreleased service objects.
*
* <p>
* If the Java Runtime Environment supports permissions, a
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundleContext.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundleContext.java
index 3e8ca046c..a9d6b51bd 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundleContext.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/BundleContext.java
@@ -391,7 +391,7 @@ public interface BundleContext extends BundleReference {
* <p>
* The following steps are required to register a service:
* <ol>
- * <li>If {@code service} is not a {@code ServiceFactory}, an
+ * <li>If {@code service} does not implement {@code ServiceFactory}, an
* {@code IllegalArgumentException} is thrown if {@code service} is not an
* {@code instanceof} all the specified class names.</li>
* <li>The Framework adds the following service properties to the service
@@ -402,6 +402,8 @@ public interface BundleContext extends BundleReference {
* registration number of the service</li>
* <li>A property named {@link Constants#OBJECTCLASS} containing all the
* specified classes.</li>
+ * <li>A property named {@link Constants#SERVICE_SCOPE} identifying the
+ * scope of the service.</li>
* </ul>
* Properties with these names in the specified {@code Dictionary} will be
* ignored.</li>
@@ -415,7 +417,8 @@ public interface BundleContext extends BundleReference {
* @param clazzes The class names under which the service can be located.
* The class names in this array will be stored in the service's
* properties under the key {@link Constants#OBJECTCLASS}.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service. The keys in the
* properties object must all be {@code String} objects. See
* {@link Constants} for a list of standard service property keys.
@@ -429,10 +432,10 @@ public interface BundleContext extends BundleReference {
* unregister the service.
* @throws IllegalArgumentException If one of the following is true:
* <ul>
- * <li>{@code service} is {@code null}.</li><li>{@code service} is
- * not a {@code ServiceFactory} object and is not an instance of all
- * the named classes in {@code clazzes}.</li><li> {@code properties}
- * contains case variants of the same key name.</li>
+ * <li>{@code service} is {@code null}.</li><li>{@code service} does
+ * not implement {@code ServiceFactory} and is not an instance of
+ * all the specified classes.</li><li> {@code properties} contains
+ * case variants of the same key name.</li>
* </ul>
* @throws SecurityException If the caller does not have the
* {@code ServicePermission} to register the service for all the
@@ -440,6 +443,7 @@ public interface BundleContext extends BundleReference {
* permissions.
* @throws IllegalStateException If this BundleContext is no longer valid.
* @see ServiceRegistration
+ * @see PrototypeServiceFactory
* @see ServiceFactory
*/
ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties);
@@ -457,7 +461,8 @@ public interface BundleContext extends BundleReference {
* than just a single string.
*
* @param clazz The class name under which the service can be located.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service.
* @return A {@code ServiceRegistration} object for use by the bundle
* registering the service to update the service's properties or to
@@ -478,7 +483,8 @@ public interface BundleContext extends BundleReference {
*
* @param <S> Type of Service.
* @param clazz The class under whose name the service can be located.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service.
* @return A {@code ServiceRegistration} object for use by the bundle
* registering the service to update the service's properties or to
@@ -737,44 +743,47 @@ public interface BundleContext extends BundleReference {
<S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException;
/**
- * Returns the service object referenced by the specified
+ * Returns the service object for the service referenced by the specified
* {@code ServiceReference} object.
+ *
* <p>
- * A bundle's use of a service is tracked by the bundle's use count of that
- * service. Each time a service's service object is returned by
- * {@link #getService(ServiceReference)} the context bundle's use count for
- * that service is incremented by one. Each time the service is released by
+ * A bundle's use of a service object obtained from this method is tracked
+ * by the bundle's use count of that service object. Each time the service
+ * object is returned by {@link #getService(ServiceReference)} the context
+ * bundle's use count for the service object is incremented by one. Each
+ * time the service object is released by
* {@link #ungetService(ServiceReference)} the context bundle's use count
- * for that service is decremented by one.
+ * for the service object is decremented by one.
+ *
* <p>
- * When a bundle's use count for a service drops to zero, the bundle should
- * no longer use that service.
+ * When a bundle's use count for the service object drops to zero, the
+ * bundle should no longer use the service object.
*
* <p>
* This method will always return {@code null} when the service associated
- * with this {@code reference} has been unregistered.
+ * with the specified {@code reference} has been unregistered.
*
* <p>
* The following steps are required to get the service object:
* <ol>
* <li>If the service has been unregistered, {@code null} is returned.</li>
- * <li>If the context bundle's use count for the service is currently zero
- * and the service was registered with an object implementing the
+ * <li>If the context bundle's use count for the service object is currently
+ * zero and the service was registered with an object implementing the
* {@code ServiceFactory} interface, the
* {@link ServiceFactory#getService(Bundle, ServiceRegistration)} method is
- * called to create a service object for the context bundle. If the service
- * object returned by the {@code ServiceFactory} object is {@code null}, not
- * an {@code instanceof} all the classes named when the service was
- * registered or the {@code ServiceFactory} object throws an exception or
- * will be recursively called for the context bundle, {@code null} is
- * returned and a Framework event of type {@link FrameworkEvent#ERROR}
- * containing a {@link ServiceException} describing the error is fired. This
- * service object is cached by the Framework. While the context bundle's use
- * count for the service is greater than zero, subsequent calls to get the
- * services's service object for the context bundle will return the cached
- * service object.</li>
- * <li>The context bundle's use count for this service is incremented by
- * one.</li>
+ * called to create the service object for the context bundle. If the
+ * service object returned by the {@code ServiceFactory} object is
+ * {@code null}, not an {@code instanceof} all the classes named when the
+ * service was registered or the {@code ServiceFactory} object throws an
+ * exception or will be recursively called for the context bundle,
+ * {@code null} is returned and a Framework event of type
+ * {@link FrameworkEvent#ERROR} containing a {@link ServiceException}
+ * describing the error is fired. This service object is cached by the
+ * Framework. While the context bundle's use count for the service object is
+ * greater than zero, subsequent calls to get the services's service object
+ * for the context bundle will return the cached service object.</li>
+ * <li>The context bundle's use count for the service object is incremented
+ * by one.</li>
* <li>The service object for the service is returned.</li>
* </ol>
*
@@ -800,25 +809,27 @@ public interface BundleContext extends BundleReference {
<S> S getService(ServiceReference<S> reference);
/**
- * Releases the service object referenced by the specified
+ * Releases the service object for the service referenced by the specified
* {@code ServiceReference} object. If the context bundle's use count for
- * the service is zero, this method returns {@code false}. Otherwise, the
- * context bundle's use count for the service is decremented by one.
+ * the service object is zero, this method returns {@code false}. Otherwise,
+ * the context bundle's use count for the service object is decremented by
+ * one.
*
* <p>
- * The service's service object should no longer be used and all references
- * to it should be destroyed when a bundle's use count for the service drops
- * to zero.
+ * The service object must no longer be used and all references to it should
+ * be destroyed when a bundle's use count for the service object drops to
+ * zero.
*
* <p>
* The following steps are required to unget the service object:
* <ol>
- * <li>If the context bundle's use count for the service is zero or the
- * service has been unregistered, {@code false} is returned.</li>
- * <li>The context bundle's use count for this service is decremented by
- * one.</li>
- * <li>If the context bundle's use count for the service is currently zero
- * and the service was registered with a {@code ServiceFactory} object, the
+ * <li>If the context bundle's use count for the service object is zero or
+ * the service has been unregistered, {@code false} is returned.</li>
+ * <li>The context bundle's use count for the service object is decremented
+ * by one.</li>
+ * <li>If the context bundle's use count for the service object is currently
+ * zero and the service was registered with a {@code ServiceFactory} object,
+ * the
* {@link ServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
* method is called to release the service object for the context bundle.</li>
* <li>{@code true} is returned.</li>
@@ -826,8 +837,8 @@ public interface BundleContext extends BundleReference {
*
* @param reference A reference to the service to be released.
* @return {@code false} if the context bundle's use count for the service
- * is zero or if the service has been unregistered; {@code true}
- * otherwise.
+ * object is zero or if the service has been unregistered;
+ * {@code true} otherwise.
* @throws IllegalStateException If this BundleContext is no longer valid.
* @throws IllegalArgumentException If the specified
* {@code ServiceReference} was not created by the same framework
@@ -838,6 +849,44 @@ public interface BundleContext extends BundleReference {
boolean ungetService(ServiceReference<?> reference);
/**
+ * Returns the {@link ServiceObjects} object for the service referenced by
+ * the specified {@code ServiceReference} object.
+ *
+ * <p>
+ * The {@link ServiceObjects} object can be used to obtain multiple
+ * service objects for services with {@link Constants#SCOPE_PROTOTYPE
+ * prototype} scope. For services with {@link Constants#SCOPE_SINGLETON
+ * singleton} or {@link Constants#SCOPE_BUNDLE bundle} scope, the
+ * {@link ServiceObjects#getService()} method behaves the same as the
+ * {@link #getService(ServiceReference)} method and the
+ * {@link ServiceObjects#ungetService(Object)} method behaves the same as
+ * the {@link #ungetService(ServiceReference)} method. That is, only one,
+ * use-counted service object is available from the {@link ServiceObjects}
+ * object.
+ *
+ * <p>
+ * This method will always return {@code null} when the service associated
+ * with the specified {@code reference} has been unregistered.
+ *
+ * @param <S> Type of Service.
+ * @param reference A reference to the service.
+ * @return A {@link ServiceObjects} object for the service associated with
+ * the specified {@code reference} or {@code null} if the service is
+ * not registered.
+ * @throws SecurityException If the caller does not have the
+ * {@code ServicePermission} to get the service using at least one
+ * of the named classes the service was registered under and the
+ * Java Runtime Environment supports permissions.
+ * @throws IllegalStateException If this BundleContext is no longer valid.
+ * @throws IllegalArgumentException If the specified
+ * {@code ServiceReference} was not created by the same framework
+ * instance as this {@code BundleContext}.
+ * @see PrototypeServiceFactory
+ * @since 1.8
+ */
+ <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference);
+
+ /**
* Creates a {@code File} object for a file in the persistent storage area
* provided for the bundle by the Framework. This method will return
* {@code null} if the platform does not have file system support.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
index 22d390f39..eb29b9d5c 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java
@@ -1342,6 +1342,53 @@ public interface Constants {
String SERVICE_DESCRIPTION = "service.description";
/**
+ * Service property identifying a service's scope.
+ *
+ * <p>
+ * This property is set by the Framework when a service is registered. If
+ * the registered object implements {@link PrototypeServiceFactory}, then
+ * the value of this service property will be {@link #SCOPE_PROTOTYPE}.
+ * Otherwise, if the registered object implements {@link ServiceFactory},
+ * then the value of this service property will be {@link #SCOPE_BUNDLE}.
+ * Otherwise, the value of this service property will be
+ * {@link #SCOPE_SINGLETON}.
+ *
+ * @since 1.8
+ * @see #SCOPE_SINGLETON
+ * @see #SCOPE_BUNDLE
+ * @see #SCOPE_PROTOTYPE
+ */
+ String SERVICE_SCOPE = "service.scope";
+
+ /**
+ * Service scope is singleton. All bundles using the service receive the
+ * same service object.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_SINGLETON = "singleton";
+
+ /**
+ * Service scope is bundle. Each bundle using the service receives a
+ * distinct service object.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_BUNDLE = "bundle";
+
+ /**
+ * Service scope is prototype. Each bundle using the service receives either
+ * a distinct service object or can request multiple distinct service
+ * objects via {@link ServiceObjects}.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_PROTOTYPE = "prototype";
+
+ /**
* Framework environment property identifying the Framework's universally
* unique identifier (UUID). A UUID represents a 128-bit value. A new UUID
* is generated by the {@link Framework#init()} method each time a framework
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PrototypeServiceFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PrototypeServiceFactory.java
new file mode 100644
index 000000000..ed860a9d0
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/PrototypeServiceFactory.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 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.
+ */
+
+package org.osgi.framework;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A factory for {@link Constants#SCOPE_PROTOTYPE prototype scope} services. The
+ * factory can provide multiple, unique service objects in the OSGi environment.
+ *
+ * <p>
+ * When registering a service, a {@code PrototypeServiceFactory} object can be
+ * used instead of a service object, so that the bundle developer can create a
+ * unique service object for each caller that is using the service.
+ *
+ * <p>
+ * When a caller uses a {@link ServiceObjects} to
+ * {@link ServiceObjects#getService() request} a service instance, the framework
+ * calls the {@link #getService(Bundle, ServiceRegistration) getService} method
+ * to return a service object specifically for the requesting caller. The caller
+ * can {@link ServiceObjects#ungetService(Object) release} the returned service
+ * object and the framework will call the
+ * {@link #ungetService(Bundle, ServiceRegistration, Object) ungetService}
+ * method with the service object.
+ *
+ * <p>
+ * When a bundle uses the {@link BundleContext#getService(ServiceReference)}
+ * method to obtain a service object, the framework must act as if the service
+ * has {@link Constants#SCOPE_BUNDLE bundle scope}. That is, the framework will
+ * call the {@link #getService(Bundle, ServiceRegistration) getService} method
+ * to obtain a bundle-scoped instance which will be cached and have a use count.
+ * See {@link ServiceFactory}.
+ *
+ * <p>
+ * A bundle can use both {@link ServiceObjects} and
+ * {@link BundleContext#getService(ServiceReference)} to obtain a service object
+ * for a service. {@link ServiceObjects#getService()} will always return an
+ * instance provided by a call to
+ * {@link #getService(Bundle, ServiceRegistration)} and
+ * {@link BundleContext#getService(ServiceReference)} will always return the
+ * bundle-scoped instance.
+ *
+ * <p>
+ * {@code PrototypeServiceFactory} objects are only used by the Framework and
+ * are not made available to other bundles in the OSGi environment. The
+ * Framework may concurrently call a {@code PrototypeServiceFactory}.
+ *
+ * @param <S> Type of Service
+ * @see BundleContext#getServiceObjects(ServiceReference)
+ * @see ServiceObjects
+ * @ThreadSafe
+ * @since 1.8
+ * @author $Id$
+ */
+@ConsumerType
+public interface PrototypeServiceFactory<S> extends ServiceFactory<S> {
+ /**
+ * Returns a service object for a caller.
+ *
+ * <p>
+ * The Framework invokes this method for each caller requesting a service
+ * object using {@link ServiceObjects#getService()}. The factory can then
+ * return a specific service object for the caller.
+ *
+ * <p>
+ * The Framework must check that the returned service object is valid. If
+ * the returned service object is {@code null} or is not an
+ * {@code instanceof} all the classes named when the service was registered,
+ * a framework event of type {@link FrameworkEvent#ERROR} is fired
+ * containing a service exception of type
+ * {@link ServiceException#FACTORY_ERROR} and {@code null} is returned to
+ * the caller. If this method throws an exception, a framework event of type
+ * {@link FrameworkEvent#ERROR} is fired containing a service exception of
+ * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception
+ * as the cause and {@code null} is returned to the caller.
+ *
+ *
+ * @param bundle The bundle requesting the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * requested service.
+ * @return A service object that <strong>must</strong> be an instance of all
+ * the classes named when the service was registered.
+ * @see ServiceObjects#getService()
+ */
+ public S getService(Bundle bundle, ServiceRegistration<S> registration);
+
+ /**
+ * Releases a service object created for a caller.
+ *
+ * <p>
+ * The Framework invokes this method when a service has been released by a
+ * bundle such as by calling {@link ServiceObjects#ungetService(Object)}.
+ * The service object may then be destroyed.
+ *
+ * <p>
+ * If this method throws an exception, a framework event of type
+ * {@link FrameworkEvent#ERROR} is fired containing a service exception of
+ * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception
+ * as the cause.
+ *
+ * @param bundle The bundle releasing the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * service being released.
+ * @param service The service object returned by a previous call to the
+ * {@link #getService(Bundle, ServiceRegistration) getService}
+ * method.
+ * @see ServiceObjects#ungetService(Object)
+ */
+ public void ungetService(Bundle bundle, ServiceRegistration<S> registration, S service);
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java
index c47ea837d..e1b3f496c 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java
@@ -19,25 +19,31 @@ package org.osgi.framework;
import org.osgi.annotation.versioning.ConsumerType;
/**
- * Allows services to provide customized service objects in the OSGi
+ * A factory for {@link Constants#SCOPE_BUNDLE bundle scope} services. The
+ * factory can provide service objects unique to each bundle in the OSGi
* environment.
*
* <p>
* When registering a service, a {@code ServiceFactory} object can be used
- * instead of a service object, so that the bundle developer can gain control of
- * the specific service object granted to a bundle that is using the service.
+ * instead of a service object, so that the bundle developer can create a unique
+ * service object for each bundle that is using the service.
*
* <p>
- * When this happens, the {@code BundleContext.getService(ServiceReference)}
- * method calls the {@code ServiceFactory.getService} method to create a service
- * object specifically for the requesting bundle. The service object returned by
- * the {@code ServiceFactory} is cached by the Framework until the bundle
- * releases its use of the service.
+ * When a bundle {@link BundleContext#getService(ServiceReference) requests} the
+ * service object, the framework calls the
+ * {@link #getService(Bundle, ServiceRegistration) getService} method to create
+ * a service object specifically for the requesting bundle. The returned service
+ * object is cached by the Framework for subsequent calls to
+ * {@link BundleContext#getService(ServiceReference)} until the bundle releases
+ * its use of the service.
*
* <p>
- * When the bundle's use count for the service is decremented to zero (including
- * the bundle stopping or the service being unregistered), the
- * {@code ServiceFactory.ungetService} method is called.
+ * When the bundle's use count for the service is
+ * {@link BundleContext#ungetService(ServiceReference) decremented} to zero
+ * (including the bundle stopping or the service being unregistered), the
+ * framework will call the
+ * {@link #ungetService(Bundle, ServiceRegistration, Object) ungetService}
+ * method.
*
* <p>
* {@code ServiceFactory} objects are only used by the Framework and are not
@@ -52,13 +58,13 @@ import org.osgi.annotation.versioning.ConsumerType;
@ConsumerType
public interface ServiceFactory<S> {
/**
- * Creates a new service object.
+ * Returns a service object for a bundle.
*
* <p>
* The Framework invokes this method the first time the specified
* {@code bundle} requests a service object using the
- * {@code BundleContext.getService(ServiceReference)} method. The service
- * factory can then return a specific service object for each bundle.
+ * {@link BundleContext#getService(ServiceReference)} method. The factory
+ * can then return a specific service object for each bundle.
*
* <p>
* The Framework must check that the returned service object is valid. If
@@ -78,9 +84,10 @@ public interface ServiceFactory<S> {
*
* <p>
* The Framework caches the valid service object and will return the same
- * service object on any future call to {@code BundleContext.getService} for
- * the specified bundle. This means the Framework must not allow this method
- * to be concurrently called for the specified bundle.
+ * service object on any future call to
+ * {@link BundleContext#getService(ServiceReference)} for the specified
+ * bundle. This means the Framework must not allow this method to be
+ * concurrently called for the specified bundle.
*
* @param bundle The bundle requesting the service.
* @param registration The {@code ServiceRegistration} object for the
@@ -92,7 +99,7 @@ public interface ServiceFactory<S> {
public S getService(Bundle bundle, ServiceRegistration<S> registration);
/**
- * Releases a service object.
+ * Releases a service object created for a bundle.
*
* <p>
* The Framework invokes this method when a service has been released by a
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceObjects.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceObjects.java
new file mode 100644
index 000000000..08a8fb70c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceObjects.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 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.
+ */
+
+package org.osgi.framework;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Allows multiple service objects for a service to be obtained.
+ *
+ * <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 ServiceObjects}
+ * object are automatically released by the framework when the bundle associated
+ * with the BundleContext used to create this {@code ServiceObjects} object is
+ * stopped.
+ *
+ * @param <S> Type of Service
+ * @see BundleContext#getServiceObjects(ServiceReference)
+ * @see PrototypeServiceFactory
+ * @ThreadSafe
+ * @noimplement
+ * @since 1.8
+ * @author $Id$
+ */
+@ProviderType
+public interface ServiceObjects<S> {
+ /**
+ * Returns a service object for the {@link #getServiceReference()
+ * referenced} service.
+ *
+ * <p>
+ * This {@code ServiceObjects} object can be used to obtain multiple service
+ * objects for the referenced service if the service has
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope. If the referenced
+ * service has {@link Constants#SCOPE_SINGLETON singleton} or
+ * {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the same
+ * as calling the {@link BundleContext#getService(ServiceReference)} method
+ * for the referenced service. That is, only one, use-counted service object
+ * is available from this {@link ServiceObjects} object.
+ *
+ * <p>
+ * This method will always return {@code null} when the referenced service
+ * has been unregistered.
+ *
+ * <p>
+ * For a prototype scope service, the following steps are required to get
+ * the service object:
+ * <ol>
+ * <li>If the referenced service has been unregistered, {@code null} is
+ * returned.</li>
+ * <li>The
+ * {@link PrototypeServiceFactory#getService(Bundle, ServiceRegistration)}
+ * method is called to create a service object for the caller.</li>
+ * <li>If the service object returned by the {@code PrototypeServiceFactory}
+ * object is {@code null}, not an {@code instanceof} all the classes named
+ * when the service was registered or the {@code PrototypeServiceFactory}
+ * object throws an exception, {@code null} is returned and a Framework
+ * event of type {@link FrameworkEvent#ERROR} containing a
+ * {@link ServiceException} describing the error is fired.</li>
+ * <li>The service object is returned.</li>
+ * </ol>
+ *
+ * @return A service object for the referenced service or {@code null} if
+ * the service is not registered, the 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 BundleContext used to create this
+ * {@code ServiceObjects} object is no longer valid.
+ * @see #ungetService(Object)
+ */
+ public S getService();
+
+ /**
+ * Releases a service object for the {@link #getServiceReference()
+ * referenced} service.
+ *
+ * <p>
+ * This {@code ServiceObjects} object can be used to obtain multiple service
+ * objects for the referenced service if the service has
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope. If the referenced
+ * service has {@link Constants#SCOPE_SINGLETON singleton} or
+ * {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the same
+ * as calling the {@link BundleContext#ungetService(ServiceReference)}
+ * method for the referenced service. That is, only one, use-counted service
+ * object is available from this {@link ServiceObjects} object.
+ *
+ * <p>
+ * For a prototype scope service, the following steps are required to
+ * release the service object:
+ * <ol>
+ * <li>If the referenced service has been unregistered, this method returns
+ * without doing anything.</li>
+ * <li>The
+ * {@link PrototypeServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
+ * method is called to release the specified service object.</li>
+ * </ol>
+ *
+ * <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 ServiceObjects} object.
+ * @throws IllegalStateException If the BundleContext used to create this
+ * {@code ServiceObjects} object is no longer valid.
+ * @throws IllegalArgumentException If the specified service was not
+ * provided by this {@code ServiceObjects} object.
+ * @see #getService()
+ */
+ public void ungetService(S service);
+
+ /**
+ * Returns the {@link ServiceReference} for the service associated with this
+ * {@code ServiceObjects} object.
+ *
+ * @return The {@link ServiceReference} for the service associated with this
+ * {@code ServiceObjects} object.
+ */
+ public ServiceReference<S> getServiceReference();
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
index baf87dc28..d97bc8a2b 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceReference.java
@@ -47,6 +47,7 @@ import org.osgi.annotation.versioning.ProviderType;
* @see BundleContext#getServiceReferences(Class, String)
* @see BundleContext#getServiceReferences(String, String)
* @see BundleContext#getService(ServiceReference)
+ * @see BundleContext#getServiceObjects(ServiceReference)
* @ThreadSafe
* @noimplement
* @author $Id$

Back to the top