diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/osgi/src')
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$ |