Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBJ Hargrave2008-08-29 01:18:21 +0000
committerBJ Hargrave2008-08-29 01:18:21 +0000
commit04999f50573271cc9269758915049ca9cc0b0538 (patch)
treeab685dcbe4ef2f16d5ed845e847da6dd329986a3
parenta726458969a725079ab544f639a466067402f340 (diff)
downloadrt.equinox.framework-04999f50573271cc9269758915049ca9cc0b0538.tar.gz
rt.equinox.framework-04999f50573271cc9269758915049ca9cc0b0538.tar.xz
rt.equinox.framework-04999f50573271cc9269758915049ca9cc0b0538.zip
Bug 245603 Refactor Service Layerv20080901
-rw-r--r--bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java2
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java7
-rw-r--r--bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ServiceRegistry.java72
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java2
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java433
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java2
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java26
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java23
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java254
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceReferenceImpl.java281
-rwxr-xr-x[-rw-r--r--]bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilteredServiceListener.java)20
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java174
-rwxr-xr-xbundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java278
-rwxr-xr-x[-rw-r--r--]bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceRegistrationImpl.java)360
-rwxr-xr-xbundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java926
-rwxr-xr-x[-rw-r--r--]bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java (renamed from bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceUse.java)49
-rw-r--r--bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java91
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java12
-rw-r--r--bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ServiceRegistryImpl.java200
19 files changed, 1765 insertions, 1447 deletions
diff --git a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java
index 237ae4d85..b9e277d71 100644
--- a/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java
+++ b/bundles/org.eclipse.osgi/console/src/org/eclipse/osgi/framework/internal/core/FrameworkCommandProvider.java
@@ -1044,7 +1044,7 @@ public class FrameworkCommandProvider implements CommandProvider, SynchronousBun
intp.print(getMessage.invoke(logentry, null));
intp.print(" "); //$NON-NLS-1$
- ServiceReferenceImpl svcref = (ServiceReferenceImpl) getServiceReference.invoke(logentry, null);
+ ServiceReference svcref = (ServiceReference) getServiceReference.invoke(logentry, null);
if (svcref != null) {
intp.print("{"); //$NON-NLS-1$
intp.print(Constants.SERVICE_ID);
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java
index 07c294de0..58e56da38 100644
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java
+++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/FrameworkAdaptor.java
@@ -175,13 +175,6 @@ public interface FrameworkAdaptor {
public PermissionStorage getPermissionStorage() throws IOException;
/**
- * Returns the <code>ServiceRegistry</code> object which will be used
- * to manage ServiceReference bindings.
- * @return The ServiceRegistry object for the adaptor.
- */
- public ServiceRegistry getServiceRegistry();
-
- /**
* The framework will call this method after the
* System BundleActivator.start(BundleContext) has been called. The context is
* the System Bundle's BundleContext. This method allows FrameworkAdaptors to
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ServiceRegistry.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ServiceRegistry.java
deleted file mode 100644
index abdd045eb..000000000
--- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/framework/adaptor/ServiceRegistry.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2005 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
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.adaptor;
-
-import org.osgi.framework.*;
-
-/**
- * The ServiceRegistry interface is used by the framework to store and
- * lookup currently registered services.
- * <p>
- * Clients may implement this interface.
- * </p>
- * @since 3.1
- */
-public interface ServiceRegistry {
-
- /**
- * Publishes a service to this ServiceRegistry.
- * @param context the BundleContext that registered the service.
- * @param serviceReg the ServiceRegistration to register.
- */
- public void publishService(BundleContext context, ServiceRegistration serviceReg);
-
- /**
- * Unpublishes a service from this ServiceRegistry
- * @param context the BundleContext that registered the service.
- * @param serviceReg the ServiceRegistration to unpublish.
- */
- public void unpublishService(BundleContext context, ServiceRegistration serviceReg);
-
- /**
- * Unpublishes all services from this ServiceRegistry that the
- * specified BundleContext registered.
- * @param context the BundleContext to unpublish all services for.
- */
- public void unpublishServices(BundleContext context);
-
- /**
- * Performs a lookup for ServiceReferences that are bound to this
- * ServiceRegistry. If both clazz and filter are null then all bound
- * ServiceReferences are returned.
- * @param clazz A fully qualified class name. All ServiceReferences that
- * reference an object that implement this class are returned. May be
- * null.
- * @param filter Used to match against published Services. All
- * ServiceReferences that match the filter are returned. If a clazz is
- * specified then all ServiceReferences that match the clazz and the
- * filter parameter are returned. May be null.
- * @return An array of all matching ServiceReferences or null
- * if none exist.
- */
- public ServiceReference[] lookupServiceReferences(String clazz, Filter filter);
-
- /**
- * Performs a lookup for ServiceReferences that are bound to this
- * ServiceRegistry using the specified BundleContext.
- * @param context The BundleContext to lookup the ServiceReferences on.
- * @return An array of all matching ServiceReferences or null if none
- * exist.
- */
- public ServiceReference[] lookupServiceReferences(BundleContext context);
-
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java
index c759b0cbf..243c08ed6 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java
@@ -1236,7 +1236,7 @@ public abstract class AbstractBundle implements Bundle, Comparable, KeyedElement
*
* @return bundle's ProtectionDomain.
*/
- protected BundleProtectionDomain getProtectionDomain() {
+ public BundleProtectionDomain getProtectionDomain() {
return domain;
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java
index a87fd01dc..caf1fd6cc 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleContextImpl.java
@@ -20,6 +20,7 @@ import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.eventmgr.EventDispatcher;
import org.eclipse.osgi.framework.eventmgr.EventListeners;
import org.eclipse.osgi.internal.profile.Profile;
+import org.eclipse.osgi.internal.serviceregistry.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -31,8 +32,6 @@ import org.osgi.framework.*;
*/
public class BundleContextImpl implements BundleContext, EventDispatcher {
- public static final String PROP_SCOPE_SERVICE_EVENTS = "osgi.scopeServiceEvents"; //$NON-NLS-1$
- public static final boolean scopeEvents = Boolean.valueOf(FrameworkProperties.getProperty(PROP_SCOPE_SERVICE_EVENTS, "true")).booleanValue(); //$NON-NLS-1$
/** true if the bundle context is still valid */
private volatile boolean valid;
@@ -45,7 +44,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
/** Internal framework object. */
final Framework framework;
- /** Services that bundle has used. Key is ServiceRegistrationImpl,
+ /** Services that bundle is using. Key is ServiceRegistrationImpl,
Value is ServiceUse */
/* @GuardedBy("contextLock") */
private HashMap/*<ServiceRegistrationImpl, ServiceUse>*/servicesInUse;
@@ -120,50 +119,12 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
}
}
+ final ServiceRegistry registry = framework.getServiceRegistry();
/* service's registered by the bundle, if any, are unregistered. */
- ServiceReference[] publishedReferences = null;
- synchronized (framework.serviceRegistry) {
- publishedReferences = framework.serviceRegistry.lookupServiceReferences(this);
- }
-
- if (publishedReferences != null) {
- for (int i = 0; i < publishedReferences.length; i++) {
- try {
- ((ServiceReferenceImpl) publishedReferences[i]).registration.unregister();
- } catch (IllegalStateException e) {
- /* already unregistered */
- }
- }
- }
+ registry.unregisterServices(this);
/* service's used by the bundle, if any, are released. */
- int usedSize;
- ServiceRegistrationImpl[] usedServices = null;
- synchronized (contextLock) {
- if (servicesInUse == null) {
- return;
- }
- synchronized (servicesInUse) {
- usedSize = servicesInUse.size();
-
- if (usedSize > 0) {
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("Releasing services"); //$NON-NLS-1$
- }
-
- usedServices = new ServiceRegistrationImpl[usedSize];
-
- Iterator regsIter = servicesInUse.keySet().iterator();
- for (int i = 0; i < usedSize; i++) {
- usedServices[i] = (ServiceRegistrationImpl) regsIter.next();
- }
- }
- }
- }
-
- for (int i = 0; i < usedSize; i++) {
- usedServices[i].releaseService(this);
- }
+ registry.releaseServicesInUse(this);
synchronized (contextLock) {
servicesInUse = null;
@@ -192,10 +153,14 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
*
* @return The context bundle's Bundle object.
*/
- public org.osgi.framework.Bundle getBundle() {
+ public Bundle getBundle() {
checkValid();
- return (bundle);
+ return getBundleImpl();
+ }
+
+ public AbstractBundle getBundleImpl() {
+ return bundle;
}
/**
@@ -209,7 +174,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @param location The location identifier of the bundle to install.
* @return The Bundle object of the installed bundle.
*/
- public org.osgi.framework.Bundle installBundle(String location) throws BundleException {
+ public Bundle installBundle(String location) throws BundleException {
checkValid();
//note AdminPermission is checked after bundle is loaded
return framework.installBundle(location);
@@ -228,7 +193,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @param in The InputStream from which the bundle will be read.
* @return The Bundle of the installed bundle.
*/
- public org.osgi.framework.Bundle installBundle(String location, InputStream in) throws BundleException {
+ public Bundle installBundle(String location, InputStream in) throws BundleException {
checkValid();
//note AdminPermission is checked after bundle is loaded
return framework.installBundle(location, in);
@@ -241,7 +206,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @return A Bundle object, or <code>null</code>
* if the identifier doesn't match any installed bundle.
*/
- public org.osgi.framework.Bundle getBundle(long id) {
+ public Bundle getBundle(long id) {
return (framework.getBundle(id));
}
@@ -265,7 +230,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @return An array of {@link AbstractBundle} objects, one
* object per installed bundle.
*/
- public org.osgi.framework.Bundle[] getBundles() {
+ public Bundle[] getBundles() {
return framework.getAllBundles();
}
@@ -308,7 +273,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
Debug.println("addServiceListener[" + bundle + "](" + listenerName + ", \"" + filter + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
- ServiceListener filteredListener = new FilteredServiceListener(filter, listener, this);
+ ServiceListener filteredListener = new FilteredServiceListener(this, listener, filter);
synchronized (framework.serviceEvent) {
checkValid();
@@ -516,8 +481,8 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* Register a service with multiple names.
* This method registers the given service object with the given properties
* under the given class names.
- * A {@link ServiceRegistrationImpl} object is returned.
- * The {@link ServiceRegistrationImpl} object is for the private use of the bundle
+ * A {@link ServiceRegistration} object is returned.
+ * The {@link ServiceRegistration} object is for the private use of the bundle
* registering the service and should not be shared with other bundles.
* The registering bundle is defined to be the context bundle.
* See {@link #getBundle()} for a definition of context bundle.
@@ -540,7 +505,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* and may now be used by other bundles.
* <li>A {@link ServiceEvent} of type {@link ServiceEvent#REGISTERED}
* is synchronously sent.
- * <li>A {@link ServiceRegistrationImpl} object for this registration
+ * <li>A {@link ServiceRegistration} object for this registration
* is returned.
* </ol>
*
@@ -552,10 +517,10 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* The keys in the properties object must all be Strings.
* Changes should not be made to this object after calling this method.
* To update the service's properties call the
- * {@link ServiceRegistrationImpl#setProperties ServiceRegistration.setProperties}
+ * {@link ServiceRegistration#setProperties ServiceRegistration.setProperties}
* method.
* This parameter may be <code>null</code> if the service has no properties.
- * @return A {@link ServiceRegistrationImpl} object for use by the bundle
+ * @return A {@link ServiceRegistration} object for use by the bundle
* registering the service to update the
* service's properties or to unregister the service.
* @exception java.lang.IllegalArgumentException If one of the following is true:
@@ -570,101 +535,13 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* and the Java runtime environment supports permissions.
* @exception java.lang.IllegalStateException
* If the bundle context has stopped.
- * @see ServiceRegistrationImpl
+ * @see ServiceRegistration
* @see ServiceFactory
*/
- public org.osgi.framework.ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) {
+ public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) {
checkValid();
- if (service == null) {
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("Service object is null"); //$NON-NLS-1$
- }
-
- throw new IllegalArgumentException(Msg.SERVICE_ARGUMENT_NULL_EXCEPTION);
- }
-
- int size = clazzes.length;
-
- if (size == 0) {
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("Classes array is empty"); //$NON-NLS-1$
- }
-
- throw new IllegalArgumentException(Msg.SERVICE_EMPTY_CLASS_LIST_EXCEPTION);
- }
-
- /* copy the array so that changes to the original will not affect us. */
- String[] copy = new String[clazzes.length];
- // doing this the hard way so we can intern the strings
- for (int i = clazzes.length - 1; i >= 0; i--)
- copy[i] = clazzes[i].intern();
- clazzes = copy;
-
- /* check for ServicePermissions. */
- framework.checkRegisterServicePermission(clazzes);
-
- if (!(service instanceof ServiceFactory)) {
- String invalidService = checkServiceClass(clazzes, service);
- if (invalidService != null) {
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
- }
- throw new IllegalArgumentException(NLS.bind(Msg.SERVICE_NOT_INSTANCEOF_CLASS_EXCEPTION, invalidService));
- }
- }
-
- return (createServiceRegistration(clazzes, service, properties));
- }
-
- //Return the name of the class that is not satisfied by the service object
- static String checkServiceClass(final String[] clazzes, final Object serviceObject) {
- ClassLoader cl = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- return serviceObject.getClass().getClassLoader();
- }
- });
- for (int i = 0; i < clazzes.length; i++) {
- try {
- Class serviceClazz = cl == null ? Class.forName(clazzes[i]) : cl.loadClass(clazzes[i]);
- if (!serviceClazz.isInstance(serviceObject))
- return clazzes[i];
- } catch (ClassNotFoundException e) {
- //This check is rarely done
- if (extensiveCheckServiceClass(clazzes[i], serviceObject.getClass()))
- return clazzes[i];
- }
- }
- return null;
- }
-
- private static boolean extensiveCheckServiceClass(String clazz, Class serviceClazz) {
- if (clazz.equals(serviceClazz.getName()))
- return false;
- Class[] interfaces = serviceClazz.getInterfaces();
- for (int i = 0; i < interfaces.length; i++)
- if (!extensiveCheckServiceClass(clazz, interfaces[i]))
- return false;
- Class superClazz = serviceClazz.getSuperclass();
- if (superClazz != null)
- if (!extensiveCheckServiceClass(clazz, superClazz))
- return false;
- return true;
- }
-
- /**
- * Create a new ServiceRegistration object. This method is used so that it may be overridden
- * by a secure implementation.
- *
- * @param clazzes The class names under which the service can be located.
- * @param service The service object or a {@link ServiceFactory} object.
- * @param properties The properties for this service.
- * @return A {@link ServiceRegistrationImpl} object for use by the bundle.
- */
- protected ServiceRegistrationImpl createServiceRegistration(String[] clazzes, Object service, Dictionary properties) {
- ServiceRegistrationImpl registration = new ServiceRegistrationImpl(this, clazzes, service);
- registration.register(properties);
- return registration;
+ return framework.getServiceRegistry().registerService(this, clazzes, service, properties);
}
/**
@@ -679,10 +556,10 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
*
* @see #registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
*/
- public org.osgi.framework.ServiceRegistration registerService(String clazz, Object service, Dictionary properties) {
+ public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) {
String[] clazzes = new String[] {clazz};
- return (registerService(clazzes, service, properties));
+ return registerService(clazzes, service, properties);
}
/**
@@ -695,11 +572,11 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
*
* <p><tt>filter</tt> is used to select the registered service whose
* properties objects contain keys and values which satisfy the filter.
- * See {@link FilterImpl}for a description of the filter string syntax.
+ * See {@link Filter}for a description of the filter string syntax.
*
* <p>If <tt>filter</tt> is <tt>null</tt>, all registered services
* are considered to match the filter.
- * <p>If <tt>filter</tt> cannot be parsed, an {@link InvalidSyntaxException}will
+ * <p>If <tt>filter</tt> cannot be parsed, an {@link InvalidSyntaxException} will
* be thrown with a human readable message where the filter became unparsable.
*
* <p>The following steps are required to select a service:
@@ -728,25 +605,19 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @exception InvalidSyntaxException If <tt>filter</tt> contains
* an invalid filter string which cannot be parsed.
*/
- public org.osgi.framework.ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+ public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("getServiceReferences(" + clazz + ", \"" + filter + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- return (framework.getServiceReferences(clazz, filter, this, false));
+ return framework.getServiceRegistry().getServiceReferences(this, clazz, filter, false);
}
public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
checkValid();
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("getAllServiceReferences(" + clazz + ", \"" + filter + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- return (framework.getServiceReferences(clazz, filter, this, true));
+ return framework.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
}
/**
* Get a service reference.
- * Retrieves a {@link ServiceReferenceImpl} for a service
+ * Retrieves a {@link ServiceReference} for a service
* which implements the named class.
*
* <p>This reference is valid at the time
@@ -756,76 +627,18 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* <p>This method is provided as a convenience for when the caller is
* interested in any service which implements a named class. This method is
* the same as calling {@link #getServiceReferences getServiceReferences}
- * with a <code>null</code> filter string but only a single {@link ServiceReferenceImpl}
+ * with a <code>null</code> filter string but only a single {@link ServiceReference}
* is returned.
*
* @param clazz The class name which the service must implement.
- * @return A {@link ServiceReferenceImpl} object, or <code>null</code>
+ * @return A {@link ServiceReference} object, or <code>null</code>
* if no services are registered which implement the named class.
* @see #getServiceReferences
*/
- public org.osgi.framework.ServiceReference getServiceReference(String clazz) {
+ public ServiceReference getServiceReference(String clazz) {
checkValid();
- if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("getServiceReference(" + clazz + ")"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- try {
- ServiceReference[] references = framework.getServiceReferences(clazz, null, this, false);
-
- if (references != null) {
- int index = 0;
-
- int length = references.length;
-
- if (length > 1) /* if more than one service, select highest ranking */{
- int rankings[] = new int[length];
- int count = 0;
- int maxRanking = Integer.MIN_VALUE;
-
- for (int i = 0; i < length; i++) {
- int ranking = ((ServiceReferenceImpl) references[i]).getRanking();
-
- rankings[i] = ranking;
-
- if (ranking > maxRanking) {
- index = i;
- maxRanking = ranking;
- count = 1;
- } else {
- if (ranking == maxRanking) {
- count++;
- }
- }
- }
-
- if (count > 1) /* if still more than one service, select lowest id */{
- long minId = Long.MAX_VALUE;
-
- for (int i = 0; i < length; i++) {
- if (rankings[i] == maxRanking) {
- long id = ((ServiceReferenceImpl) references[i]).getId();
-
- if (id < minId) {
- index = i;
- minId = id;
- }
- }
- }
- }
- }
-
- return (references[index]);
- }
- } catch (InvalidSyntaxException e) {
- if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
- Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
- Debug.printStackTrace(e);
- }
- }
-
- return (null);
+ return framework.getServiceRegistry().getServiceReference(this, clazz);
}
/**
@@ -878,7 +691,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @see #ungetService
* @see ServiceFactory
*/
- public Object getService(org.osgi.framework.ServiceReference reference) {
+ public Object getService(ServiceReference reference) {
checkValid();
synchronized (contextLock) {
@@ -887,11 +700,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
servicesInUse = new HashMap(10);
}
- ServiceRegistrationImpl registration = ((ServiceReferenceImpl) reference).registration;
-
- framework.checkGetServicePermission(registration.clazzes);
-
- return registration.getService(BundleContextImpl.this);
+ return framework.getServiceRegistry().getService(this, (ServiceReferenceImpl) reference);
}
/**
@@ -929,12 +738,10 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @see #getService
* @see ServiceFactory
*/
- public boolean ungetService(org.osgi.framework.ServiceReference reference) {
+ public boolean ungetService(ServiceReference reference) {
checkValid();
- ServiceRegistrationImpl registration = ((ServiceReferenceImpl) reference).registration;
-
- return registration.ungetService(BundleContextImpl.this);
+ return framework.getServiceRegistry().ungetService(this, (ServiceReferenceImpl) reference);
}
/**
@@ -971,7 +778,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* Call bundle's BundleActivator.start()
* This method is called by Bundle.startWorker to start the bundle.
*
- * @exception org.osgi.framework.BundleException if
+ * @exception BundleException if
* the bundle has a class that implements the BundleActivator interface,
* but Framework couldn't instantiate it, or the BundleActivator.start()
* method failed
@@ -1037,7 +844,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* Call bundle's BundleActivator.stop()
* This method is called by Bundle.stopWorker to stop the bundle.
*
- * @exception org.osgi.framework.BundleException if
+ * @exception BundleException if
* the bundle has a class that implements the BundleActivator interface,
* and the BundleActivator.stop() method failed
*/
@@ -1069,126 +876,13 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
}
}
- /**
- * Provides a list of {@link ServiceReference}s for the services
- * registered by this bundle
- * or <code>null</code> if the bundle has no registered
- * services.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReference} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceRegistrationImpl
- * @see ServiceReferenceImpl
- */
- protected ServiceReference[] getRegisteredServices() {
- ServiceReference[] services = null;
-
- synchronized (framework.serviceRegistry) {
- services = framework.serviceRegistry.lookupServiceReferences(this);
- if (services == null) {
- return null;
- }
- int removed = 0;
- for (int i = services.length - 1; i >= 0; i--) {
- ServiceReferenceImpl ref = (ServiceReferenceImpl) services[i];
- String[] classes = ref.getClasses();
- try { /* test for permission to the classes */
- framework.checkGetServicePermission(classes);
- } catch (SecurityException se) {
- services[i] = null;
- removed++;
- }
- }
- if (removed > 0) {
- ServiceReference[] temp = services;
- services = new ServiceReference[temp.length - removed];
- for (int i = temp.length - 1; i >= 0; i--) {
- if (temp[i] == null)
- removed--;
- else
- services[i - removed] = temp[i];
- }
- }
- }
- return (services);
-
- }
-
- /**
- * Provides a list of {@link ServiceReferenceImpl}s for the
- * services this bundle is using,
- * or <code>null</code> if the bundle is not using any services.
- * A bundle is considered to be using a service if the bundle's
- * use count for the service is greater than zero.
- *
- * <p>The list is valid at the time
- * of the call to this method, but the framework is a very dynamic
- * environment and services can be modified or unregistered at anytime.
- *
- * @return An array of {@link ServiceReferenceImpl} or <code>null</code>.
- * @exception java.lang.IllegalStateException If the
- * bundle has been uninstalled.
- * @see ServiceReferenceImpl
- */
- protected ServiceReferenceImpl[] getServicesInUse() {
- synchronized (contextLock) {
- if (servicesInUse == null) {
- return null;
- }
-
- synchronized (servicesInUse) {
- int size = servicesInUse.size();
-
- if (size == 0) {
- return null;
- }
-
- ServiceReferenceImpl[] references = new ServiceReferenceImpl[size];
- int refcount = 0;
-
- Iterator regsIter = servicesInUse.keySet().iterator();
-
- for (int i = 0; i < size; i++) {
- ServiceRegistrationImpl service = (ServiceRegistrationImpl) regsIter.next();
-
- try {
- framework.checkGetServicePermission(service.clazzes);
- } catch (SecurityException se) {
- continue;
- }
-
- references[refcount] = (ServiceReferenceImpl) service.getReference();
- refcount++;
- }
-
- if (refcount < size) {
- if (refcount == 0) {
- return null;
- }
-
- ServiceReferenceImpl[] refs = references;
- references = new ServiceReferenceImpl[refcount];
-
- System.arraycopy(refs, 0, references, 0, refcount);
- }
-
- return references;
- }
- }
- }
-
/**
* Return the map of ServiceRegistrationImpl to ServiceUse for services being
* used by this context.
* @return A map of ServiceRegistrationImpl to ServiceUse for services in use by
* this context.
*/
- Map getServicesInUseMap() {
+ public Map getServicesInUseMap() {
synchronized (contextLock) {
return servicesInUse;
}
@@ -1284,31 +978,6 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
}
/**
- * Check for permission to listen to a service.
- */
- protected boolean hasListenServicePermission(ServiceEvent event) {
- ProtectionDomain domain = bundle.getProtectionDomain();
-
- if (domain != null) {
- ServiceReferenceImpl reference = (ServiceReferenceImpl) event.getServiceReference();
-
- String[] names = reference.getClasses();
-
- int len = names.length;
-
- for (int i = 0; i < len; i++) {
- if (domain.implies(new ServicePermission(names[i], ServicePermission.GET))) {
- return true;
- }
- }
-
- return false;
- }
-
- return (true);
- }
-
- /**
* Construct a Filter object. This filter object may be used
* to match a ServiceReference or a Dictionary.
* See Filter
@@ -1319,10 +988,10 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @exception InvalidSyntaxException If the filter parameter contains
* an invalid filter string which cannot be parsed.
*/
- public org.osgi.framework.Filter createFilter(String filter) throws InvalidSyntaxException {
+ public Filter createFilter(String filter) throws InvalidSyntaxException {
checkValid();
- return (new FilterImpl(filter));
+ return new FilterImpl(filter);
}
/**
@@ -1332,7 +1001,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
* @exception java.lang.IllegalStateException
* If the context bundle has stopped.
*/
- protected void checkValid() {
+ public void checkValid() {
if (!isValid()) {
throw new IllegalStateException(Msg.BUNDLE_CONTEXT_INVALID_EXCEPTION);
}
@@ -1347,13 +1016,7 @@ public class BundleContextImpl implements BundleContext, EventDispatcher {
return valid;
}
- boolean isAssignableTo(ServiceReferenceImpl reference) {
- if (!scopeEvents)
- return true;
- String[] clazzes = reference.getClasses();
- for (int i = 0; i < clazzes.length; i++)
- if (!reference.isAssignableTo(bundle, clazzes[i]))
- return false;
- return true;
+ public Framework getFramework() {
+ return framework;
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java
index 92dfa563c..0c5bfc4e7 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java
@@ -245,7 +245,7 @@ public class BundleFragment extends AbstractBundle {
* @return An array of {@link ServiceReference} or <code>null</code>.
* @exception java.lang.IllegalStateException If the
* bundle has been uninstalled.
- * @see ServiceRegistrationImpl
+ * @see ServiceRegistration
* @see ServiceReference
*/
public ServiceReference[] getRegisteredServices() {
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
index 54505d5b7..249504ed0 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java
@@ -478,7 +478,7 @@ public class BundleHost extends AbstractBundle {
}
/**
- * Provides a list of {@link ServiceReferenceImpl}s for the services
+ * Provides a list of {@link ServiceReference}s for the services
* registered by this bundle
* or <code>null</code> if the bundle has no registered
* services.
@@ -487,24 +487,24 @@ public class BundleHost extends AbstractBundle {
* of the call to this method, but the framework is a very dynamic
* environment and services can be modified or unregistered at anytime.
*
- * @return An array of {@link ServiceReferenceImpl} or <code>null</code>.
+ * @return An array of {@link ServiceReference} or <code>null</code>.
* @exception java.lang.IllegalStateException If the
* bundle has been uninstalled.
- * @see ServiceRegistrationImpl
- * @see ServiceReferenceImpl
+ * @see ServiceRegistration
+ * @see ServiceReference
*/
- public org.osgi.framework.ServiceReference[] getRegisteredServices() {
+ public ServiceReference[] getRegisteredServices() {
checkValid();
if (context == null) {
- return (null);
+ return null;
}
- return (context.getRegisteredServices());
+ return context.getFramework().getServiceRegistry().getRegisteredServices(context);
}
/**
- * Provides a list of {@link ServiceReferenceImpl}s for the
+ * Provides a list of {@link ServiceReference}s for the
* services this bundle is using,
* or <code>null</code> if the bundle is not using any services.
* A bundle is considered to be using a service if the bundle's
@@ -514,19 +514,19 @@ public class BundleHost extends AbstractBundle {
* of the call to this method, but the framework is a very dynamic
* environment and services can be modified or unregistered at anytime.
*
- * @return An array of {@link ServiceReferenceImpl} or <code>null</code>.
+ * @return An array of {@link ServiceReference} or <code>null</code>.
* @exception java.lang.IllegalStateException If the
* bundle has been uninstalled.
- * @see ServiceReferenceImpl
+ * @see ServiceReference
*/
- public org.osgi.framework.ServiceReference[] getServicesInUse() {
+ public ServiceReference[] getServicesInUse() {
checkValid();
if (context == null) {
- return (null);
+ return null;
}
- return (context.getServicesInUse());
+ return context.getFramework().getServiceRegistry().getServicesInUse(context);
}
protected Bundle[] getFragments() {
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java
index b8d8ea0ad..a245513f9 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilterImpl.java
@@ -15,13 +15,10 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Iterator;
-
+import java.util.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.util.Headers;
+import org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
@@ -159,7 +156,7 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
* <code>false</code> otherwise.
*/
public boolean match(org.osgi.framework.ServiceReference reference) {
- return match0(((ServiceReferenceImpl) reference).registration.getProperties());
+ return match0(((ServiceReferenceImpl) reference).getRegistration().getProperties());
}
/**
@@ -376,20 +373,6 @@ public class FilterImpl implements Filter /* since Framework 1.1 */{
}
/**
- * Filter using a service's properties.
- * The Filter is executed using the referenced service's
- * properties.
- *
- * @param reference A reference to the service whose
- * properties are used in the match.
- * @return If the service's properties match the filter,
- * return <code>true</code>. Otherwise, return <code>false</code>.
- */
- protected boolean match(ServiceReferenceImpl reference) {
- return match0(reference.registration.getProperties());
- }
-
- /**
* Internal match routine.
* Dictionary parameter must support case-insensitive get.
*
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java
index 9f54e2f29..8627753ff 100644
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/Framework.java
@@ -28,6 +28,7 @@ import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
import org.eclipse.osgi.internal.profile.Profile;
+import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -58,7 +59,7 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
* the adaptor will be merged into these properties.
*/
protected Properties properties;
- /** Has the service space been started */
+ /** Has the framework been started */
protected boolean active;
/** The bundles installed in the framework */
protected BundleRepository bundles;
@@ -69,9 +70,7 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
/** Startlevel object. This object manages the framework and bundle startlevels */
protected StartLevelManager startLevelManager;
/** The ServiceRegistry */
- protected ServiceRegistry serviceRegistry; //TODO This is duplicated from the adaptor, do we really gain ?
- /** next free service id. */
- protected long serviceid;
+ private ServiceRegistry serviceRegistry;
/*
* The following EventListeners objects keep track of event listeners
@@ -210,8 +209,7 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done new EventManager"); //$NON-NLS-1$ //$NON-NLS-2$
/* create the service registry */
- serviceid = 1;
- serviceRegistry = adaptor.getServiceRegistry();
+ serviceRegistry = new ServiceRegistry();
// Initialize the installLock; there is no way of knowing
// what the initial size should be, at most it will be the number
// of threads trying to install a bundle (probably a very low number).
@@ -250,6 +248,14 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
Profile.logExit("Framework.initialize()"); //$NON-NLS-1$
}
+ public FrameworkAdaptor getAdaptor() {
+ return adaptor;
+ }
+
+ public ServiceRegistry getServiceRegistry() {
+ return serviceRegistry;
+ }
+
private void setNLSFrameworkLog() {
try {
Field frameworkLogField = NLS.class.getDeclaredField("frameworkLog"); //$NON-NLS-1$
@@ -1152,121 +1158,6 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
}
/**
- * Returns a list of <tt>ServiceReference</tt> objects. This method
- * returns a list of <tt>ServiceReference</tt> objects for services which
- * implement and were registered under the specified class and match the
- * specified filter criteria.
- *
- * <p>
- * The list is valid at the time of the call to this method, however as the
- * Framework is a very dynamic environment, services can be modified or
- * unregistered at anytime.
- *
- * <p>
- * <tt>filter</tt> is used to select the registered service whose
- * properties objects contain keys and values which satisfy the filter. See
- * {@link FilterImpl}for a description of the filter string syntax.
- *
- * <p>
- * If <tt>filter</tt> is <tt>null</tt>, all registered services are
- * considered to match the filter.
- * <p>
- * If <tt>filter</tt> cannot be parsed, an {@link InvalidSyntaxException}
- * will be thrown with a human readable message where the filter became
- * unparsable.
- *
- * <p>
- * The following steps are required to select a service:
- * <ol>
- * <li>If the Java Runtime Environment supports permissions, the caller is
- * checked for the <tt>ServicePermission</tt> to get the service with the
- * specified class. If the caller does not have the correct permission,
- * <tt>null</tt> is returned.
- * <li>If the filter string is not <tt>null</tt>, the filter string is
- * parsed and the set of registered services which satisfy the filter is
- * produced. If the filter string is <tt>null</tt>, then all registered
- * services are considered to satisfy the filter.
- * <li>If <code>clazz</code> is not <tt>null</tt>, the set is further
- * reduced to those services which are an <tt>instanceof</tt> and were
- * registered under the specified class. The complete list of classes of
- * which a service is an instance and which were specified when the service
- * was registered is available from the service's
- * {@link Constants#OBJECTCLASS}property.
- * <li>An array of <tt>ServiceReference</tt> to the selected services is
- * returned.
- * </ol>
- *
- * @param clazz
- * The class name with which the service was registered, or <tt>null</tt>
- * for all services.
- * @param filterstring
- * The filter criteria.
- * @return An array of <tt>ServiceReference</tt> objects, or <tt>null</tt>
- * if no services are registered which satisfy the search.
- * @exception InvalidSyntaxException
- * If <tt>filter</tt> contains an invalid filter string
- * which cannot be parsed.
- */
- protected ServiceReference[] getServiceReferences(String clazz, String filterstring, BundleContextImpl context, boolean allservices) throws InvalidSyntaxException {
- FilterImpl filter = (filterstring == null) ? null : new FilterImpl(filterstring);
- ServiceReference[] services = null;
- if (clazz != null) {
- try /* test for permission to get clazz */{
- checkGetServicePermission(clazz);
- } catch (SecurityException se) {
- return (null);
- }
- }
- synchronized (serviceRegistry) {
- services = serviceRegistry.lookupServiceReferences(clazz, filter);
- if (services == null) {
- return null;
- }
- int removed = 0;
- for (int i = services.length - 1; i >= 0; i--) {
- ServiceReferenceImpl ref = (ServiceReferenceImpl) services[i];
- String[] classes = ref.getClasses();
- if (allservices || context.isAssignableTo((ServiceReferenceImpl) services[i])) {
- if (clazz == null)
- try { /* test for permission to the classes */
- checkGetServicePermission(classes);
- } catch (SecurityException se) {
- services[i] = null;
- removed++;
- }
- } else {
- services[i] = null;
- removed++;
- }
- }
- if (removed > 0) {
- ServiceReference[] temp = services;
- services = new ServiceReference[temp.length - removed];
- for (int i = temp.length - 1; i >= 0; i--) {
- if (temp[i] == null)
- removed--;
- else
- services[i - removed] = temp[i];
- }
- }
-
- }
- return services == null || services.length == 0 ? null : services;
- }
-
- /**
- * Method to return the next available service id. This method should be
- * called while holding the registrations lock.
- *
- * @return next service id.
- */
- protected long getNextServiceId() {
- long id = serviceid;
- serviceid++;
- return (id);
- }
-
- /**
* Creates a <code>File</code> object for a file in the persistent
* storage area provided for the bundle by the framework. If the adaptor
* does not have file system support, this method will return <code>null</code>.
@@ -1310,53 +1201,6 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
}
/**
- * Check for permission to register a service.
- *
- * The caller must have permission for ALL names.
- */
- protected void checkRegisterServicePermission(String[] names) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- int len = names.length;
- for (int i = 0; i < len; i++) {
- sm.checkPermission(new ServicePermission(names[i], ServicePermission.REGISTER));
- }
- }
- }
-
- /**
- * Check for permission to get a service.
- *
- * The caller must have permission for at least ONE name.
- */
- protected void checkGetServicePermission(String[] names) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- SecurityException se = null;
- int len = names.length;
- for (int i = 0; i < len; i++) {
- try {
- sm.checkPermission(new ServicePermission(names[i], ServicePermission.GET));
- return;
- } catch (SecurityException e) {
- se = e;
- }
- }
- throw se;
- }
- }
-
- /**
- * Check for permission to get a service.
- */
- protected void checkGetServicePermission(String name) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(new ServicePermission(name, ServicePermission.GET));
- }
- }
-
- /**
* This is necessary for running from a JXE, otherwise the SecurityManager
* is set much later than we would like!
*/
@@ -1885,4 +1729,78 @@ public class Framework implements EventDispatcher, EventPublisher, Runnable {
}
}
}
+
+ /**
+ * Used by ServiceReferenceImpl for isAssignableTo
+ * @param registrant Bundle registering service
+ * @param client Bundle desiring to use service
+ * @param className class name to use
+ * @param serviceClass class of original service object
+ * @return true if assignable given package wiring
+ */
+ public boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className, Class serviceClass) {
+ // always return false for fragments
+ AbstractBundle consumer = (AbstractBundle) client;
+ if (consumer.isFragment())
+ return false;
+ // 1) if the registrant == consumer always return true
+ AbstractBundle producer = (AbstractBundle) registrant;
+ if (consumer == producer)
+ return true;
+ // 2) get the package name from the specified className
+ String pkgName = BundleLoader.getPackageName(className);
+ if (pkgName.startsWith("java.")) //$NON-NLS-1$
+ return true;
+ BundleLoader producerBL = producer.getBundleLoader();
+ if (producerBL == null)
+ return false;
+ BundleLoader consumerBL = consumer.getBundleLoader();
+ if (consumerBL == null)
+ return false;
+ // 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
+ PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
+ if (consumerSource == null)
+ return true;
+ // work around the issue when the package is in the EE and we delegate to boot for that package
+ if (producerBL.isBootDelegationPackage(pkgName)) {
+ SystemBundleLoader systemLoader = (SystemBundleLoader) systemBundle.getBundleLoader();
+ if (systemLoader.isEEPackage(pkgName))
+ return true; // in this case we have a common source from the EE
+ }
+ // 4) For the registrant bundle, find the wiring for the package.
+ PackageSource producerSource = producerBL.getPackageSource(pkgName);
+ if (producerSource == null) {
+ // 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object. If no wiring is found return false.
+ producerSource = getPackageSource(serviceClass, pkgName);
+ if (producerSource == null)
+ return false;
+ }
+ // 6) If the two wirings found are equal then return true; otherwise return false.
+ return producerSource.hasCommonSource(consumerSource);
+ }
+
+ private PackageSource getPackageSource(Class serviceClass, String pkgName) {
+ if (serviceClass == null)
+ return null;
+ AbstractBundle serviceBundle = (AbstractBundle) packageAdmin.getBundle(serviceClass);
+ if (serviceBundle == null)
+ return null;
+ BundleLoader producerBL = serviceBundle.getBundleLoader();
+ if (producerBL == null)
+ return null;
+ PackageSource producerSource = producerBL.getPackageSource(pkgName);
+ if (producerSource != null)
+ return producerSource;
+ // try the interfaces
+ Class[] interfaces = serviceClass.getInterfaces();
+ // note that getInterfaces never returns null
+ for (int i = 0; i < interfaces.length; i++) {
+ producerSource = getPackageSource(interfaces[i], pkgName);
+ if (producerSource != null)
+ return producerSource;
+ }
+ // try super class
+ return getPackageSource(serviceClass.getSuperclass(), pkgName);
+ }
+
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceReferenceImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceReferenceImpl.java
deleted file mode 100644
index d4698b768..000000000
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceReferenceImpl.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2008 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
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
-
-/**
- * A reference to a service.
- *
- * The framework returns ServiceReference objects from the
- * {@link BundleContextImpl#getServiceReference BundleContext.getServiceReference} and
- * {@link BundleContextImpl#getServiceReferences BundleContext.getServiceReferences} methods.
- * <p>A ServiceReference may be shared between bundles and
- * can be used to examine the properties of the service and to
- * get the service object
- * (See {@link BundleContextImpl#getService BundleContext.getService}).
- * <p>A registered service <i>may</i> have multiple, distinct ServiceReference
- * objects which refer to it.
- * However these ServiceReference objects will have
- * the same <code>hashCode</code> and the <code>equals</code> method
- * will return <code>true</code> when compared.
- */
-
-public class ServiceReferenceImpl implements ServiceReference, Comparable {
- /** Registered Service object. */
- final ServiceRegistrationImpl registration;
-
- /**
- * Construct a reference.
- *
- */
- protected ServiceReferenceImpl(ServiceRegistrationImpl registration) {
- this.registration = registration;
- /* We must not dereference registration in the constructor
- * since it is "leaked" to us in the ServiceRegistrationImpl
- * constructor.
- */
- }
-
- /**
- * Get the value of a service's property.
- *
- * <p>This method will continue to return property values after the
- * service has been unregistered. This is so that references to
- * unregistered service can be interrogated.
- * (For example: ServiceReference objects stored in the log.)
- *
- * @param key Name of the property.
- * @return Value of the property or <code>null</code> if there is
- * no property by that name.
- */
- public Object getProperty(String key) {
- return (registration.getProperty(key));
- }
-
- /**
- * Get the list of key names for the service's properties.
- *
- * <p>This method will continue to return the keys after the
- * service has been unregistered. This is so that references to
- * unregistered service can be interrogated.
- * (For example: ServiceReference objects stored in the log.)
- *
- * @return The list of property key names.
- */
- public String[] getPropertyKeys() {
- return (registration.getPropertyKeys());
- }
-
- /**
- * Return the bundle which registered the service.
- *
- * <p>This method will always return <code>null</code> when the
- * service has been unregistered. This can be used to
- * determine if the service has been unregistered.
- *
- * @return The bundle which registered the service.
- */
- public org.osgi.framework.Bundle getBundle() {
- return (registration.getBundle());
- }
-
- /**
- * Return the list of bundles which are using the service.
- *
- * <p>This method will always return <code>null</code> when the
- * service has been unregistered.
- *
- * @return The array of bundles using the service or null if
- * no bundles are using the service.
- * @see BundleContextImpl#getService
- */
- public org.osgi.framework.Bundle[] getUsingBundles() {
- return (registration.getUsingBundles());
- }
-
- /**
- * Return the classes under which the referenced service was registered.
- *
- * @return array of class names.
- */
- protected String[] getClasses() {
- return (registration.clazzes);
- }
-
- /**
- * Return the service id of the ServiceRegistration.
- *
- * @return service.id of the service
- */
- protected long getId() {
- return registration.getId();
- }
-
- /**
- * Return the service ranking of the ServiceRegistration.
- *
- * @return service.ranking of the service
- */
- protected int getRanking() {
- return registration.getRanking();
- }
-
- /**
- * Returns a hash code value for the object.
- *
- * @return a hash code value for this object.
- */
- public int hashCode() {
- return (registration.hashCode());
- }
-
- /**
- * Indicates whether some other object is "equal to" this one.
- *
- * @param obj the reference object with which to compare.
- * @return <code>true</code> if this object is the same as the obj
- * argument; <code>false</code> otherwise.
- */
- public boolean equals(Object obj) {
- if (obj == this) {
- return (true);
- }
-
- if (!(obj instanceof ServiceReferenceImpl)) {
- return (false);
- }
-
- ServiceReferenceImpl other = (ServiceReferenceImpl) obj;
-
- return (registration == other.registration);
- }
-
- /**
- * Return a string representation of this reference.
- *
- * @return String
- */
- public String toString() {
- return (registration.toString());
- }
-
- /**
- *
- * Compares two service objects and returns an indication as to which is higher ranked
- * based on service ranking and service_ID.
- *
- * The service with the higher service ranking (as specified in its service.ranking property)
- * is defined to be higher ranked.
- *
- * If there is a tie in ranking, the service with the lowest
- * service ID (as specified in its service.id property); that is,
- * the service that was registered first is returned.
- *
- * This is the same algorithm used by BundleContext.getServiceReference.
- *
- * @return int
- * int = 0 if this object's ranking and
- * service id are equivalent
- *
- * int < 0 if this object's ranking is lower
- * than the argument's ranking or if the
- * rankings are equal, this object's service
- * id is greater than the argument's service
- * id.
- *
- * int > 0 if this object's ranking is higher
- * than than the argument's ranking or if the
- * rankings are equal, this object's service
- * id is less than the argument's service id.
- *
- *
- * @param object
- * an object to compare the receiver to
- * @exception ClassCastException
- * if the argument can not be converted
- * into something comparable with the
- * receiver.
- */
- public int compareTo(Object object) {
- ServiceReferenceImpl other = (ServiceReferenceImpl) object;
- if (this.getRanking() != other.getRanking())
- return this.getRanking() > other.getRanking() ? -1 : 1;
- return this.getId() == other.getId() ? 0 : this.getId() > other.getId() ? 1 : -1;
- }
-
- public boolean isAssignableTo(Bundle bundle, String className) {
- AbstractBundle consumer = (AbstractBundle) bundle;
- // always return false for fragments
- if (consumer.isFragment())
- return false;
- BundleHost producer = (BundleHost) registration.bundle;
- // 1) if the registrant == consumer always return true
- if (consumer == producer)
- return true;
- // 2) get the package name from the specified className
- String pkgName = BundleLoader.getPackageName(className);
- if (pkgName.startsWith("java.")) //$NON-NLS-1$
- return true;
- BundleLoader producerBL = producer.getBundleLoader();
- if (producerBL == null)
- return false;
- BundleLoader consumerBL = consumer.getBundleLoader();
- if (consumerBL == null)
- return false;
- // 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
- PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
- if (consumerSource == null)
- return true;
- // work around the issue when the package is in the EE and we delegate to boot for that package
- if (producerBL.isBootDelegationPackage(pkgName)) {
- SystemBundleLoader systemLoader = (SystemBundleLoader) registration.framework.systemBundle.getBundleLoader();
- if (systemLoader.isEEPackage(pkgName))
- return true; // in this case we have a common source from the EE
- }
- // 4) For the registrant bundle, find the wiring for the package.
- PackageSource producerSource = producerBL.getPackageSource(pkgName);
- if (producerSource == null) {
- // 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object. If no wiring is found return false.
- producerSource = getPackageSource(registration.service.getClass(), pkgName);
- if (producerSource == null)
- return false;
- }
- // 6) If the two wirings found are equal then return true; otherwise return false.
- return producerSource.hasCommonSource(consumerSource);
- }
-
- private PackageSource getPackageSource(Class serviceClass, String pkgName) {
- if (serviceClass == null)
- return null;
- AbstractBundle serviceBundle = (AbstractBundle) registration.framework.packageAdmin.getBundle(serviceClass);
- if (serviceBundle == null)
- return null;
- BundleLoader producerBL = serviceBundle.getBundleLoader();
- if (producerBL == null)
- return null;
- PackageSource producerSource = producerBL.getPackageSource(pkgName);
- if (producerSource != null)
- return producerSource;
- // try the interfaces
- Class[] interfaces = serviceClass.getInterfaces();
- // note that getInterfaces never returns null
- for (int i = 0; i < interfaces.length; i++) {
- producerSource = getPackageSource(interfaces[i], pkgName);
- if (producerSource != null)
- return producerSource;
- }
- // try super class
- return getPackageSource(serviceClass.getSuperclass(), pkgName);
- }
-}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilteredServiceListener.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
index db40e365a..0fed85ac3 100644..100755
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/FilteredServiceListener.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/FilteredServiceListener.java
@@ -9,9 +9,11 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.serviceregistry;
import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.framework.internal.core.BundleContextImpl;
+import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.osgi.framework.*;
public class FilteredServiceListener implements ServiceListener {
@@ -36,7 +38,7 @@ public class FilteredServiceListener implements ServiceListener {
* @param listener real listener.
* @exception InvalidSyntaxException if the filter is invalid.
*/
- protected FilteredServiceListener(String filterstring, ServiceListener listener, BundleContextImpl context) throws InvalidSyntaxException {
+ public FilteredServiceListener(BundleContextImpl context, ServiceListener listener, String filterstring) throws InvalidSyntaxException {
if (filterstring == null) {
this.filter = null;
this.objectClass = null;
@@ -59,10 +61,9 @@ public class FilteredServiceListener implements ServiceListener {
}
/**
- * Receive notification that a service has had a
- * change occur in it's lifecycle.
- *
- * @param event The ServiceEvent.
+ * Receives notification that a service has had a lifecycle change.
+ *
+ * @param event The <code>ServiceEvent</code> object.
*/
public void serviceChanged(ServiceEvent event) {
ServiceReferenceImpl reference = (ServiceReferenceImpl) event.getServiceReference();
@@ -78,12 +79,12 @@ public class FilteredServiceListener implements ServiceListener {
return; // no class in this event matches a required part of the filter; we do not need to deliver this event
}
- if (!context.hasListenServicePermission(event))
+ if (!ServiceRegistry.hasListenServicePermission(event, context))
return;
if (Debug.DEBUG && Debug.DEBUG_EVENTS) {
String listenerName = this.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(this)); //$NON-NLS-1$
- Debug.println("filterServiceEvent(" + listenerName + ", \"" + filter + "\", " + reference.registration.getProperties() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ Debug.println("filterServiceEvent(" + listenerName + ", \"" + filter + "\", " + reference.getRegistration().getProperties() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
checkfilter: {
@@ -107,7 +108,7 @@ public class FilteredServiceListener implements ServiceListener {
return; // there is a filter and it does not match, so do NOT deliver the event
}
- if (allservices || context.isAssignableTo(reference)) {
+ if (allservices || ServiceRegistry.isAssignableTo(context, reference)) {
if (Debug.DEBUG && Debug.DEBUG_EVENTS) {
String listenerName = listener.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(listener)); //$NON-NLS-1$
Debug.println("dispatchFilteredServiceEvent(" + listenerName + ")"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -125,5 +126,4 @@ public class FilteredServiceListener implements ServiceListener {
public String toString() {
return filter == null ? listener.toString() : filter.toString();
}
-
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java
new file mode 100644
index 000000000..d88982007
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java
@@ -0,0 +1,174 @@
+package org.eclipse.osgi.internal.serviceregistry;
+
+import java.lang.reflect.Array;
+import java.util.*;
+import org.eclipse.osgi.framework.util.Headers;
+import org.osgi.framework.Constants;
+
+/**
+ * Hashtable for service properties.
+ *
+ * Supports case-insensitive key lookup.
+ */
+class ServiceProperties extends Headers {
+ /**
+ * Create a properties object for the service.
+ *
+ * @param props The properties for this service.
+ */
+ private ServiceProperties(int size, Dictionary props) {
+ super(size);
+
+ if (props != null) {
+ synchronized (props) {
+ Enumeration keysEnum = props.keys();
+
+ while (keysEnum.hasMoreElements()) {
+ Object key = keysEnum.nextElement();
+
+ if (key instanceof String) {
+ String header = (String) key;
+
+ setProperty(header, props.get(header));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a properties object for the service.
+ *
+ * @param props The properties for this service.
+ */
+ ServiceProperties(Dictionary props) {
+ this((props == null) ? 2 : props.size() + 2, props);
+ }
+
+ /**
+ * Get a clone of the value of a service's property.
+ *
+ * @param key header name.
+ * @return Clone of the value of the property or <code>null</code> if there is
+ * no property by that name.
+ */
+ Object getProperty(String key) {
+ return cloneValue(get(key));
+ }
+
+ /**
+ * Get the list of key names for the service's properties.
+ *
+ * @return The list of property key names.
+ */
+ synchronized String[] getPropertyKeys() {
+ int size = size();
+
+ String[] keynames = new String[size];
+
+ Enumeration keysEnum = keys();
+
+ for (int i = 0; i < size; i++) {
+ keynames[i] = (String) keysEnum.nextElement();
+ }
+
+ return keynames;
+ }
+
+ /**
+ * Put a clone of the property value into this property object.
+ *
+ * @param key Name of property.
+ * @param value Value of property.
+ * @return previous property value.
+ */
+ synchronized Object setProperty(String key, Object value) {
+ return set(key, cloneValue(value));
+ }
+
+ /**
+ * Attempt to clone the value if necessary and possible.
+ *
+ * For some strange reason, you can test to see of an Object is
+ * Cloneable but you can't call the clone method since it is
+ * protected on Object!
+ *
+ * @param value object to be cloned.
+ * @return cloned object or original object if we didn't clone it.
+ */
+ static Object cloneValue(Object value) {
+ if (value == null)
+ return null;
+ if (value instanceof String) /* shortcut String */
+ return (value);
+ if (value instanceof Number) /* shortcut Number */
+ return value;
+ if (value instanceof Character) /* shortcut Character */
+ return value;
+ if (value instanceof Boolean) /* shortcut Boolean */
+ return value;
+
+ Class clazz = value.getClass();
+ if (clazz.isArray()) {
+ // Do an array copy
+ Class type = clazz.getComponentType();
+ int len = Array.getLength(value);
+ Object clonedArray = Array.newInstance(type, len);
+ System.arraycopy(value, 0, clonedArray, 0, len);
+ return clonedArray;
+ }
+ // must use reflection because Object clone method is protected!!
+ try {
+ return (clazz.getMethod("clone", null).invoke(value, null)); //$NON-NLS-1$
+ } catch (Exception e) {
+ /* clone is not a public method on value's class */
+ } catch (Error e) {
+ /* JCL does not support reflection; try some well known types */
+ if (value instanceof Vector)
+ return ((Vector) value).clone();
+ if (value instanceof Hashtable)
+ return ((Hashtable) value).clone();
+ }
+ return value;
+ }
+
+ public synchronized String toString() {
+ String keys[] = getPropertyKeys();
+
+ int size = keys.length;
+
+ StringBuffer sb = new StringBuffer(20 * size);
+
+ sb.append('{');
+
+ int n = 0;
+ for (int i = 0; i < size; i++) {
+ String key = keys[i];
+ if (!key.equals(Constants.OBJECTCLASS)) {
+ if (n > 0)
+ sb.append(", "); //$NON-NLS-1$
+
+ sb.append(key);
+ sb.append('=');
+ Object value = get(key);
+ if (value.getClass().isArray()) {
+ sb.append('[');
+ int length = Array.getLength(value);
+ for (int j = 0; j < length; j++) {
+ if (j > 0)
+ sb.append(',');
+ sb.append(Array.get(value, j));
+ }
+ sb.append(']');
+ } else {
+ sb.append(value);
+ }
+ n++;
+ }
+ }
+
+ sb.append('}');
+
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
new file mode 100755
index 000000000..954e94b2f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceReferenceImpl.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.serviceregistry;
+
+import org.osgi.framework.*;
+
+/**
+ * A reference to a service.
+ *
+ * <p>
+ * The Framework returns <code>ServiceReference</code> objects from the
+ * <code>BundleContext.getServiceReference</code> and
+ * <code>BundleContext.getServiceReferences</code> methods.
+ * <p>
+ * A <code>ServiceReference</code> object may be shared between bundles and
+ * can be used to examine the properties of the service and to get the service
+ * object.
+ * <p>
+ * Every service registered in the Framework has a unique
+ * <code>ServiceRegistration</code> object and may have multiple, distinct
+ * <code>ServiceReference</code> objects referring to it.
+ * <code>ServiceReference</code> objects associated with a
+ * <code>ServiceRegistration</code> object have the same <code>hashCode</code>
+ * and are considered equal (more specifically, their <code>equals()</code>
+ * method will return <code>true</code> when compared).
+ * <p>
+ * If the same service object is registered multiple times,
+ * <code>ServiceReference</code> objects associated with different
+ * <code>ServiceRegistration</code> objects are not equal.
+ *
+ * @see BundleContext#getServiceReference
+ * @see BundleContext#getServiceReferences
+ * @see BundleContext#getService
+ * @ThreadSafe
+ */
+public class ServiceReferenceImpl implements ServiceReference, Comparable {
+ /** Registered Service object. */
+ private final ServiceRegistrationImpl registration;
+
+ /**
+ * Construct a reference.
+ *
+ */
+ ServiceReferenceImpl(ServiceRegistrationImpl registration) {
+ this.registration = registration;
+ /* We must not dereference registration in the constructor
+ * since it is "leaked" to us in the ServiceRegistrationImpl
+ * constructor.
+ */
+ }
+
+ /**
+ * Returns the property value to which the specified property key is mapped
+ * in the properties <code>Dictionary</code> object of the service
+ * referenced by this <code>ServiceReference</code> object.
+ *
+ * <p>
+ * Property keys are case-insensitive.
+ *
+ * <p>
+ * This method must continue to return property values after the service has
+ * been unregistered. This is so references to unregistered services (for
+ * example, <code>ServiceReference</code> objects stored in the log) can
+ * still be interrogated.
+ *
+ * @param key The property key.
+ * @return The property value to which the key is mapped; <code>null</code>
+ * if there is no property named after the key.
+ */
+ public Object getProperty(String key) {
+ return registration.getProperty(key);
+ }
+
+ /**
+ * Returns an array of the keys in the properties <code>Dictionary</code>
+ * object of the service referenced by this <code>ServiceReference</code>
+ * object.
+ *
+ * <p>
+ * This method will continue to return the keys after the service has been
+ * unregistered. This is so references to unregistered services (for
+ * example, <code>ServiceReference</code> objects stored in the log) can
+ * still be interrogated.
+ *
+ * <p>
+ * This method is <i>case-preserving </i>; this means that every key in the
+ * returned array must have the same case as the corresponding key in the
+ * properties <code>Dictionary</code> that was passed to the
+ * {@link BundleContext#registerService(String[],Object,java.util.Dictionary)}
+ * or {@link ServiceRegistration#setProperties} methods.
+ *
+ * @return An array of property keys.
+ */
+ public String[] getPropertyKeys() {
+ return registration.getPropertyKeys();
+ }
+
+ /**
+ * Returns the bundle that registered the service referenced by this
+ * <code>ServiceReference</code> object.
+ *
+ * <p>
+ * This method must return <code>null</code> when the service has been
+ * unregistered. This can be used to determine if the service has been
+ * unregistered.
+ *
+ * @return The bundle that registered the service referenced by this
+ * <code>ServiceReference</code> object; <code>null</code> if
+ * that service has already been unregistered.
+ * @see BundleContext#registerService(String[],Object,java.util.Dictionary)
+ */
+ public Bundle getBundle() {
+ return registration.getBundle();
+ }
+
+ /**
+ * Returns the bundles that are using the service referenced by this
+ * <code>ServiceReference</code> object. Specifically, this method returns
+ * the bundles whose usage count for that service is greater than zero.
+ *
+ * @return An array of bundles whose usage count for the service referenced
+ * by this <code>ServiceReference</code> object is greater than
+ * zero; <code>null</code> if no bundles are currently using that
+ * service.
+ *
+ * @since 1.1
+ */
+ public Bundle[] getUsingBundles() {
+ return registration.getUsingBundles();
+ }
+
+ /**
+ * Tests if the bundle that registered the service referenced by this
+ * <code>ServiceReference</code> and the specified bundle use the same
+ * source for the package of the specified class name.
+ * <p>
+ * This method performs the following checks:
+ * <ol>
+ * <li>Get the package name from the specified class name.</li>
+ * <li>For the bundle that registered the service referenced by this
+ * <code>ServiceReference</code> (registrant bundle); find the source for
+ * the package. If no source is found then return <code>true</code> if the
+ * registrant bundle is equal to the specified bundle; otherwise return
+ * <code>false</code>.</li>
+ * <li>If the package source of the registrant bundle is equal to the
+ * package source of the specified bundle then return <code>true</code>;
+ * otherwise return <code>false</code>.</li>
+ * </ol>
+ *
+ * @param bundle The <code>Bundle</code> object to check.
+ * @param className The class name to check.
+ * @return <code>true</code> if the bundle which registered the service
+ * referenced by this <code>ServiceReference</code> and the
+ * specified bundle use the same source for the package of the
+ * specified class name. Otherwise <code>false</code> is returned.
+ *
+ * @since 1.3
+ */
+ public boolean isAssignableTo(Bundle bundle, String className) {
+ return registration.isAssignableTo(bundle, className);
+ }
+
+ /**
+ * Compares this <code>ServiceReference</code> with the specified
+ * <code>ServiceReference</code> for order.
+ *
+ * <p>
+ * If this <code>ServiceReference</code> and the specified
+ * <code>ServiceReference</code> have the same
+ * {@link Constants#SERVICE_ID service id} they are equal. This
+ * <code>ServiceReference</code> is less than the specified
+ * <code>ServiceReference</code> if it has a lower
+ * {@link Constants#SERVICE_RANKING service ranking} and greater if it has a
+ * higher service ranking. Otherwise, if this <code>ServiceReference</code>
+ * and the specified <code>ServiceReference</code> have the same
+ * {@link Constants#SERVICE_RANKING service ranking}, this
+ * <code>ServiceReference</code> is less than the specified
+ * <code>ServiceReference</code> if it has a higher
+ * {@link Constants#SERVICE_ID service id} and greater if it has a lower
+ * service id.
+ *
+ * @param reference The <code>ServiceReference</code> to be compared.
+ * @return Returns a negative integer, zero, or a positive integer if this
+ * <code>ServiceReference</code> is less than, equal to, or
+ * greater than the specified <code>ServiceReference</code>.
+ * @since 1.4
+ */
+ public int compareTo(Object object) {
+ ServiceReferenceImpl other = (ServiceReferenceImpl) object;
+ if (this.getRanking() != other.getRanking())
+ return this.getRanking() > other.getRanking() ? -1 : 1;
+ return this.getId() == other.getId() ? 0 : this.getId() > other.getId() ? 1 : -1;
+ }
+
+ /**
+ * Returns a hash code value for the object.
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return registration.hashCode();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param obj the reference object with which to compare.
+ * @return <code>true</code> if this object is the same as the obj
+ * argument; <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return (true);
+ }
+
+ if (!(obj instanceof ServiceReferenceImpl)) {
+ return (false);
+ }
+
+ ServiceReferenceImpl other = (ServiceReferenceImpl) obj;
+
+ return registration == other.registration;
+ }
+
+ /**
+ * Return a string representation of this reference.
+ *
+ * @return String
+ */
+ public String toString() {
+ return registration.toString();
+ }
+
+ /**
+ * Return the ServiceRegistrationImpl for this ServiceReferenceImpl.
+ *
+ * @return The ServiceRegistrationImpl for this ServiceReferenceImpl.
+ */
+ public ServiceRegistrationImpl getRegistration() {
+ return registration;
+ }
+
+ /**
+ * Return the classes under which the referenced service was registered.
+ *
+ * @return array of class names.
+ */
+ String[] getClasses() {
+ return registration.getClasses();
+ }
+
+ /**
+ * Return the service id of the ServiceRegistration.
+ *
+ * @return service.id of the service
+ */
+ long getId() {
+ return registration.getId();
+ }
+
+ /**
+ * Return the service ranking of the ServiceRegistration.
+ *
+ * @return service.ranking of the service
+ */
+ int getRanking() {
+ return registration.getRanking();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceRegistrationImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
index 9ee488af8..7a8db27f8 100644..100755
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceRegistrationImpl.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java
@@ -9,13 +9,13 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.serviceregistry;
-import java.lang.reflect.Array;
import java.util.*;
import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.util.Headers;
+import org.eclipse.osgi.framework.internal.core.*;
import org.osgi.framework.*;
+import org.osgi.framework.Constants;
/**
* A registered service.
@@ -31,34 +31,38 @@ import org.osgi.framework.*;
* the service. This implies that if a
* bundle wants to keep its service registered, it should keep the
* ServiceRegistration object referenced.
+ *
+ * @ThreadSafe
*/
public class ServiceRegistrationImpl implements ServiceRegistration {
- /** Reference to this registration. */
- /* @GuardedBy("registrationLock") */
- private ServiceReferenceImpl reference;
-
/** Internal framework object. */
- final Framework framework;
+ private final Framework framework;
+
+ private final ServiceRegistry registry;
/** context which registered this service. */
- final BundleContextImpl context;
+ private final BundleContextImpl context;
/** bundle which registered this service. */
- final AbstractBundle bundle;
-
- /** list of contexts using the service.
- /* @GuardedBy("registrationLock") */
- private ArrayList contextsUsing;
+ private final Bundle bundle;
/** service classes for this registration. */
- final String[] clazzes;
+ private final String[] clazzes;
/** service object for this registration. */
- final Object service;
+ private final Object service;
+
+ /** Reference to this registration. */
+ /* @GuardedBy("registrationLock") */
+ private ServiceReferenceImpl reference;
+
+ /** list of contexts using the service. */
+ /* @GuardedBy("registrationLock") */
+ private ArrayList contextsUsing;
/** properties for this registration. */
/* @GuardedBy("registrationLock") */
- private Properties properties;
+ private ServiceProperties properties;
/** service id. */
/* @GuardedBy("registrationLock") */
@@ -83,10 +87,11 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
* in the framework's service registry.
*
*/
- protected ServiceRegistrationImpl(BundleContextImpl context, String[] clazzes, Object service) {
+ ServiceRegistrationImpl(ServiceRegistry registry, BundleContextImpl context, String[] clazzes, Object service) {
+ this.registry = registry;
this.context = context;
- this.bundle = context.bundle;
- this.framework = context.framework;
+ this.bundle = context.getBundleImpl();
+ this.framework = context.getFramework();
this.clazzes = clazzes; /* must be set before calling createProperties. */
this.service = service;
synchronized (registrationLock) {
@@ -105,17 +110,17 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*/
void register(Dictionary props) {
final ServiceReference ref;
- synchronized (framework.serviceRegistry) {
+ synchronized (registry) {
context.checkValid();
synchronized (registrationLock) {
ref = reference; /* used to publish event outside sync */
- serviceid = framework.getNextServiceId(); /* must be set before calling createProperties. */
+ serviceid = registry.getNextServiceId(); /* must be set before calling createProperties. */
this.properties = createProperties(props); /* must be valid after unregister is called. */
}
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
Debug.println("registerService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.serviceRegistry.publishService(context, this);
+ registry.addServiceRegistration(context, this);
}
/* must not hold the registrations lock when this event is published */
@@ -123,6 +128,43 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
}
/**
+ * Update the properties associated with this service.
+ *
+ * <p>The key "objectClass" cannot be modified by this method. It's
+ * value is set when the service is registered.
+ *
+ * <p>The following steps are followed to modify a service's properties:
+ * <ol>
+ * <li>The service's properties are replaced with the provided properties.
+ * <li>A {@link ServiceEvent} of type {@link ServiceEvent#MODIFIED}
+ * is synchronously sent.
+ * </ol>
+ *
+ * @param props The properties for this service.
+ * Changes should not be made to this object after calling this method.
+ * To update the service's properties this method should be called again.
+ * @exception java.lang.IllegalStateException If
+ * this ServiceRegistration has already been unregistered.
+ *
+ * @exception IllegalArgumentException If the <tt>properties</tt>
+ * parameter contains case variants of the same key name.
+ */
+ public void setProperties(Dictionary props) {
+ final ServiceReference ref;
+ synchronized (registrationLock) {
+ if (state != REGISTERED) { /* in the process of unregistering */
+ throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
+ }
+
+ ref = reference; /* used to publish event outside sync */
+ this.properties = createProperties(props);
+ }
+
+ /* must not hold the registrationLock when this event is published */
+ framework.publishServiceEvent(ServiceEvent.MODIFIED, ref);
+ }
+
+ /**
* Unregister the service.
* Remove a service registration from the framework's service
* registry.
@@ -154,10 +196,9 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*/
public void unregister() {
final ServiceReference ref;
- synchronized (framework.serviceRegistry) {
+ synchronized (registry) {
synchronized (registrationLock) {
- if (state != REGISTERED) /* in the process of unregisterING */
- {
+ if (state != REGISTERED) { /* in the process of unregisterING */
throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
}
@@ -166,7 +207,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
Debug.println("unregisterService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- framework.serviceRegistry.unpublishService(context, this);
+ registry.removeServiceRegistration(context, this);
state = UNREGISTERING; /* mark unregisterING */
ref = reference; /* used to publish event outside sync */
@@ -217,7 +258,11 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
* this ServiceRegistration has already been unregistered.
* @return A {@link ServiceReferenceImpl} object.
*/
- public org.osgi.framework.ServiceReference getReference() {
+ public ServiceReference getReference() {
+ return getReferenceImpl();
+ }
+
+ ServiceReferenceImpl getReferenceImpl() {
/* use reference instead of unregistered so that ServiceFactorys, called
* by releaseService after the registration is unregistered, can
* get the ServiceReference. Note this technically may violate the spec
@@ -233,69 +278,31 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
}
/**
- * Update the properties associated with this service.
- *
- * <p>The key "objectClass" cannot be modified by this method. It's
- * value is set when the service is registered.
- *
- * <p>The following steps are followed to modify a service's properties:
- * <ol>
- * <li>The service's properties are replaced with the provided properties.
- * <li>A {@link ServiceEvent} of type {@link ServiceEvent#MODIFIED}
- * is synchronously sent.
- * </ol>
- *
- * @param props The properties for this service.
- * Changes should not be made to this object after calling this method.
- * To update the service's properties this method should be called again.
- * @exception java.lang.IllegalStateException If
- * this ServiceRegistration has already been unregistered.
- *
- * @exception IllegalArgumentException If the <tt>properties</tt>
- * parameter contains case variants of the same key name.
- */
- public void setProperties(Dictionary props) {
- final ServiceReference ref;
- synchronized (registrationLock) {
- if (state != REGISTERED) /* in the process of unregistering */
- {
- throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
- }
-
- ref = reference; /* used to publish event outside sync */
- this.properties = createProperties(props);
- }
-
- /* must not hold the registrationLock when this event is published */
- framework.publishServiceEvent(ServiceEvent.MODIFIED, ref);
- }
-
- /**
* Construct a properties object from the dictionary for this
* ServiceRegistration.
*
- * @param props The properties for this service.
+ * @param p The properties for this service.
* @return A Properties object for this ServiceRegistration.
*/
/* @GuardedBy("registrationLock") */
- private Properties createProperties(Dictionary props) {
- Properties properties = new Properties(props);
+ private ServiceProperties createProperties(Dictionary p) {
+ ServiceProperties props = new ServiceProperties(p);
- properties.set(Constants.OBJECTCLASS, clazzes, true);
- properties.set(Constants.SERVICE_ID, new Long(serviceid), true);
- properties.setReadOnly();
- Object ranking = properties.getProperty(Constants.SERVICE_RANKING);
+ props.set(Constants.OBJECTCLASS, clazzes, true);
+ props.set(Constants.SERVICE_ID, new Long(serviceid), true);
+ props.setReadOnly();
+ Object ranking = props.getProperty(Constants.SERVICE_RANKING);
serviceranking = (ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0;
- return properties;
+ return props;
}
/**
* Return the properties object. This is for framework internal use only.
* @return The service registration's properties.
*/
- Properties getProperties() {
+ public ServiceProperties getProperties() {
synchronized (registrationLock) {
return properties;
}
@@ -313,7 +320,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
* @return Value of the property or <code>null</code> if there is
* no property by that name.
*/
- protected Object getProperty(String key) {
+ Object getProperty(String key) {
synchronized (registrationLock) {
return properties.getProperty(key);
}
@@ -329,7 +336,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*
* @return The list of property key names.
*/
- protected String[] getPropertyKeys() {
+ String[] getPropertyKeys() {
synchronized (registrationLock) {
return properties.getPropertyKeys();
}
@@ -355,6 +362,14 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
}
}
+ String[] getClasses() {
+ return clazzes;
+ }
+
+ Object getService() {
+ return service;
+ }
+
/**
* Return the bundle which registered the service.
*
@@ -364,7 +379,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*
* @return The bundle which registered the service.
*/
- protected AbstractBundle getBundle() {
+ Bundle getBundle() {
synchronized (registrationLock) {
if (reference == null) {
return null;
@@ -380,14 +395,14 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
* @param user BundleContext using service.
* @return Service object
*/
- protected Object getService(BundleContextImpl user) {
+ Object getService(BundleContextImpl user) {
synchronized (registrationLock) {
if (state == UNREGISTERED) { /* service unregistered */
return null;
}
}
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("getService[" + user.bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Debug.println("getService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
Map servicesInUse = user.getServicesInUseMap();
@@ -452,7 +467,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
* is zero or if the service has been unregistered,
* otherwise <code>true</code>.
*/
- protected boolean ungetService(BundleContextImpl user) {
+ boolean ungetService(BundleContextImpl user) {
synchronized (registrationLock) {
if (state == UNREGISTERED) {
return false;
@@ -460,7 +475,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
}
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("ungetService[" + user.bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Debug.println("ungetService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
Map servicesInUse = user.getServicesInUseMap();
@@ -495,7 +510,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*
* @param user BundleContext using service.
*/
- protected void releaseService(BundleContextImpl user) {
+ void releaseService(BundleContextImpl user) {
synchronized (registrationLock) {
if (reference == null) { /* registration dead */
return;
@@ -503,7 +518,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
}
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("releaseService[" + user.bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ Debug.println("releaseService[" + user.getBundleImpl() + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
Map servicesInUse = user.getServicesInUseMap();
@@ -533,7 +548,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
*
* @return Array of Bundles using this service.
*/
- protected AbstractBundle[] getUsingBundles() {
+ Bundle[] getUsingBundles() {
synchronized (registrationLock) {
if (state == UNREGISTERED) /* service unregistered */
return null;
@@ -546,21 +561,24 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
return null;
/* Copy list of BundleContext into an array of Bundle. */
- AbstractBundle[] bundles = new AbstractBundle[size];
+ Bundle[] bundles = new Bundle[size];
for (int i = 0; i < size; i++)
- bundles[i] = ((BundleContextImpl) contextsUsing.get(i)).bundle;
+ bundles[i] = ((BundleContextImpl) contextsUsing.get(i)).getBundleImpl();
return bundles;
}
}
+ boolean isAssignableTo(Bundle client, String className) {
+ return framework.isServiceAssignableTo(bundle, client, className, service.getClass());
+ }
+
/**
* Return a String representation of this object.
*
* @return String representation of this object.
*/
public String toString() {
- String[] clazzes = this.clazzes;
int size = clazzes.length;
StringBuffer sb = new StringBuffer(50 * size);
@@ -578,170 +596,4 @@ public class ServiceRegistrationImpl implements ServiceRegistration {
return sb.toString();
}
-
- /**
- * Hashtable for service properties.
- */
- static class Properties extends Headers {
- /**
- * Create a properties object for the service.
- *
- * @param props The properties for this service.
- */
- private Properties(int size, Dictionary props) {
- super(size);
-
- if (props != null) {
- synchronized (props) {
- Enumeration keysEnum = props.keys();
-
- while (keysEnum.hasMoreElements()) {
- Object key = keysEnum.nextElement();
-
- if (key instanceof String) {
- String header = (String) key;
-
- setProperty(header, props.get(header));
- }
- }
- }
- }
- }
-
- /**
- * Create a properties object for the service.
- *
- * @param props The properties for this service.
- */
- protected Properties(Dictionary props) {
- this((props == null) ? 2 : props.size() + 2, props);
- }
-
- /**
- * Get a clone of the value of a service's property.
- *
- * @param key header name.
- * @return Clone of the value of the property or <code>null</code> if there is
- * no property by that name.
- */
- protected Object getProperty(String key) {
- return (cloneValue(get(key)));
- }
-
- /**
- * Get the list of key names for the service's properties.
- *
- * @return The list of property key names.
- */
- protected synchronized String[] getPropertyKeys() {
- int size = size();
-
- String[] keynames = new String[size];
-
- Enumeration keysEnum = keys();
-
- for (int i = 0; i < size; i++) {
- keynames[i] = (String) keysEnum.nextElement();
- }
-
- return (keynames);
- }
-
- /**
- * Put a clone of the property value into this property object.
- *
- * @param key Name of property.
- * @param value Value of property.
- * @return previous property value.
- */
- protected synchronized Object setProperty(String key, Object value) {
- return (set(key, cloneValue(value)));
- }
-
- /**
- * Attempt to clone the value if necessary and possible.
- *
- * For some strange reason, you can test to see of an Object is
- * Cloneable but you can't call the clone method since it is
- * protected on Object!
- *
- * @param value object to be cloned.
- * @return cloned object or original object if we didn't clone it.
- */
- protected static Object cloneValue(Object value) {
- if (value == null)
- return null;
- if (value instanceof String) /* shortcut String */
- return (value);
- if (value instanceof Number) /* shortcut Number */
- return value;
- if (value instanceof Character) /* shortcut Character */
- return value;
- if (value instanceof Boolean) /* shortcut Boolean */
- return value;
-
- Class clazz = value.getClass();
- if (clazz.isArray()) {
- // Do an array copy
- Class type = clazz.getComponentType();
- int len = Array.getLength(value);
- Object clonedArray = Array.newInstance(type, len);
- System.arraycopy(value, 0, clonedArray, 0, len);
- return clonedArray;
- }
- // must use reflection because Object clone method is protected!!
- try {
- return (clazz.getMethod("clone", null).invoke(value, null)); //$NON-NLS-1$
- } catch (Exception e) {
- /* clone is not a public method on value's class */
- } catch (Error e) {
- /* JCL does not support reflection; try some well known types */
- if (value instanceof Vector)
- return (((Vector) value).clone());
- if (value instanceof Hashtable)
- return (((Hashtable) value).clone());
- }
- return (value);
- }
-
- public synchronized String toString() {
- String keys[] = getPropertyKeys();
-
- int size = keys.length;
-
- StringBuffer sb = new StringBuffer(20 * size);
-
- sb.append('{');
-
- int n = 0;
- for (int i = 0; i < size; i++) {
- String key = keys[i];
- if (!key.equals(Constants.OBJECTCLASS)) {
- if (n > 0)
- sb.append(", "); //$NON-NLS-1$
-
- sb.append(key);
- sb.append('=');
- Object value = get(key);
- if (value.getClass().isArray()) {
- sb.append('[');
- int length = Array.getLength(value);
- for (int j = 0; j < length; j++) {
- if (j > 0)
- sb.append(',');
- sb.append(Array.get(value, j));
- }
- sb.append(']');
- } else {
- sb.append(value);
- }
- n++;
- }
- }
-
- sb.append('}');
-
- return (sb.toString());
- }
- }
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
new file mode 100755
index 000000000..d159302d4
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistry.java
@@ -0,0 +1,926 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.serviceregistry;
+
+import java.security.*;
+import java.util.*;
+import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.framework.internal.core.*;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.*;
+import org.osgi.framework.Constants;
+
+/**
+ * The Service Registry. This class is the main control point for service
+ * layer operations in the framework.
+ *
+ * @ThreadSafe
+ */
+public class ServiceRegistry {
+ public static final String PROP_SCOPE_SERVICE_EVENTS = "osgi.scopeServiceEvents"; //$NON-NLS-1$
+ public static final boolean scopeEvents = Boolean.valueOf(FrameworkProperties.getProperty(PROP_SCOPE_SERVICE_EVENTS, "true")).booleanValue(); //$NON-NLS-1$
+
+ /** Published services by class name. Key is a String class name; Value is a ArrayList of ServiceRegistrations */
+ /* @GuardedBy("this") */
+ private final HashMap/*<String,ArrayList<ServiceRegistrationImpl>>*/publishedServicesByClass;
+ /** All published services. Value is ServiceRegistrations */
+ /* @GuardedBy("this") */
+ private final ArrayList/*<ServiceRegistrationImpl>*/allPublishedServices;
+ /** Published services by BundleContext. Key is a BundleContext; Value is a ArrayList of ServiceRegistrations*/
+ /* @GuardedBy("this") */
+ private final HashMap/*<BundleContextImpl,ArrayList<ServiceRegistrationImpl>*/publishedServicesByContext;
+ /** next free service id. */
+ /* @GuardedBy("this") */
+ private long serviceid;
+ /** initial capacity of the data structure */
+ private static final int initialCapacity = 50;
+
+ /**
+ * Initializes the internal data structures of this ServiceRegistry.
+ *
+ */
+ public ServiceRegistry() {
+ serviceid = 1;
+ publishedServicesByClass = new HashMap(initialCapacity);
+ publishedServicesByContext = new HashMap(initialCapacity);
+ allPublishedServices = new ArrayList(initialCapacity);
+ }
+
+ /**
+ * Registers the specified service object with the specified properties
+ * under the specified class names into the Framework. A
+ * <code>ServiceRegistration</code> object is returned. The
+ * <code>ServiceRegistration</code> object is for the private use of the
+ * bundle registering the service and should not be shared with other
+ * bundles. The registering bundle is defined to be the context bundle.
+ * Other bundles can locate the service by using either the
+ * {@link #getServiceReferences} or {@link #getServiceReference} method.
+ *
+ * <p>
+ * A bundle can register a service object that implements the
+ * {@link ServiceFactory} interface to have more flexibility in providing
+ * service objects to other bundles.
+ *
+ * <p>
+ * The following steps are required to register a service:
+ * <ol>
+ * <li>If <code>service</code> is not a <code>ServiceFactory</code>,
+ * an <code>IllegalArgumentException</code> is thrown if
+ * <code>service</code> is not an <code>instanceof</code> all the
+ * classes named.
+ * <li>The Framework adds these service properties to the specified
+ * <code>Dictionary</code> (which may be <code>null</code>): a property
+ * named {@link Constants#SERVICE_ID} identifying the registration number of
+ * the service and a property named {@link Constants#OBJECTCLASS} containing
+ * all the specified classes. If any of these properties have already been
+ * specified by the registering bundle, their values will be overwritten by
+ * the Framework.
+ * <li>The service is added to the Framework service registry and may now
+ * be used by other bundles.
+ * <li>A service event of type {@link ServiceEvent#REGISTERED} is fired.
+ * <li>A <code>ServiceRegistration</code> object for this registration is
+ * returned.
+ * </ol>
+ *
+ * @param context The BundleContext of the registering bundle.
+ * @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</code>
+ * object.
+ * @param properties The properties for this service. The keys in the
+ * properties object must all be <code>String</code> objects. See
+ * {@link Constants} for a list of standard service property keys.
+ * Changes should not be made to this object after calling this
+ * method. To update the service's properties the
+ * {@link ServiceRegistration#setProperties} method must be called.
+ * The set of properties may be <code>null</code> if the service
+ * has no properties.
+ *
+ * @return A <code>ServiceRegistration</code> object for use by the bundle
+ * registering the service to update the service's properties or to
+ * unregister the service.
+ *
+ * @throws java.lang.IllegalArgumentException If one of the following is
+ * true:
+ * <ul>
+ * <li><code>service</code> is <code>null</code>.
+ * <li><code>service</code> is not a <code>ServiceFactory</code>
+ * object and is not an instance of all the named classes in
+ * <code>clazzes</code>.
+ * <li><code>properties</code> contains case variants of the same
+ * key name.
+ * </ul>
+ *
+ * @throws java.lang.SecurityException If the caller does not have the
+ * <code>ServicePermission</code> to register the service for all
+ * the named classes and the Java Runtime Environment supports
+ * permissions.
+ *
+ * @throws java.lang.IllegalStateException If this BundleContext is no
+ * longer valid.
+ *
+ * @see ServiceRegistration
+ * @see ServiceFactory
+ */
+ public ServiceRegistrationImpl registerService(BundleContextImpl context, String[] clazzes, Object service, Dictionary properties) {
+ if (service == null) {
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println("Service object is null"); //$NON-NLS-1$
+ }
+
+ throw new IllegalArgumentException(Msg.SERVICE_ARGUMENT_NULL_EXCEPTION);
+ }
+
+ int size = clazzes.length;
+
+ if (size == 0) {
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println("Classes array is empty"); //$NON-NLS-1$
+ }
+
+ throw new IllegalArgumentException(Msg.SERVICE_EMPTY_CLASS_LIST_EXCEPTION);
+ }
+
+ /* copy the array so that changes to the original will not affect us. */
+ String[] copy = new String[clazzes.length];
+ // doing this the hard way so we can intern the strings
+ for (int i = clazzes.length - 1; i >= 0; i--)
+ copy[i] = clazzes[i].intern();
+ clazzes = copy;
+
+ /* check for ServicePermissions. */
+ checkRegisterServicePermission(clazzes);
+
+ if (!(service instanceof ServiceFactory)) {
+ String invalidService = checkServiceClass(clazzes, service);
+ if (invalidService != null) {
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
+ }
+ throw new IllegalArgumentException(NLS.bind(Msg.SERVICE_NOT_INSTANCEOF_CLASS_EXCEPTION, invalidService));
+ }
+ }
+
+ ServiceRegistrationImpl registration = new ServiceRegistrationImpl(this, context, clazzes, service);
+ registration.register(properties);
+ return registration;
+
+ }
+
+ /**
+ * Returns an array of <code>ServiceReference</code> objects. The returned
+ * array of <code>ServiceReference</code> objects contains services that
+ * were registered under the specified class, match the specified filter
+ * criteria, and the packages for the class names under which the services
+ * were registered match the context bundle's packages as defined in
+ * {@link ServiceReference#isAssignableTo(Bundle, String)}.
+ *
+ * <p>
+ * The list is valid at the time of the call to this method, however since
+ * the Framework is a very dynamic environment, services can be modified or
+ * unregistered at anytime.
+ *
+ * <p>
+ * <code>filter</code> is used to select the registered service whose
+ * properties objects contain keys and values which satisfy the filter. See
+ * {@link Filter} for a description of the filter string syntax.
+ *
+ * <p>
+ * If <code>filter</code> is <code>null</code>, all registered services
+ * are considered to match the filter. If <code>filter</code> cannot be
+ * parsed, an {@link InvalidSyntaxException} will be thrown with a human
+ * readable message where the filter became unparsable.
+ *
+ * <p>
+ * The following steps are required to select a set of
+ * <code>ServiceReference</code> objects:
+ * <ol>
+ * <li>If the filter string is not <code>null</code>, the filter string
+ * is parsed and the set <code>ServiceReference</code> objects of
+ * registered services that satisfy the filter is produced. If the filter
+ * string is <code>null</code>, then all registered services are
+ * considered to satisfy the filter.
+ * <li>If the Java Runtime Environment supports permissions, the set of
+ * <code>ServiceReference</code> objects produced by the previous step is
+ * reduced by checking that the caller has the
+ * <code>ServicePermission</code> to get at least one of the class names
+ * under which the service was registered. If the caller does not have the
+ * correct permission for a particular <code>ServiceReference</code>
+ * object, then it is removed from the set.
+ * <li>If <code>clazz</code> is not <code>null</code>, the set is
+ * further reduced to those services that are an <code>instanceof</code>
+ * and were registered under the specified class. The complete list of
+ * classes of which a service is an instance and which were specified when
+ * the service was registered is available from the service's
+ * {@link Constants#OBJECTCLASS} property.
+ * <li>The set is reduced one final time by cycling through each
+ * <code>ServiceReference</code> object and calling
+ * {@link ServiceReference#isAssignableTo(Bundle, String)} with the context
+ * bundle and each class name under which the <code>ServiceReference</code>
+ * object was registered. For any given <code>ServiceReference</code>
+ * object, if any call to
+ * {@link ServiceReference#isAssignableTo(Bundle, String)} returns
+ * <code>false</code>, then it is removed from the set of
+ * <code>ServiceReference</code> objects.
+ * <li>An array of the remaining <code>ServiceReference</code> objects is
+ * returned.
+ * </ol>
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @param clazz The class name with which the service was registered or
+ * <code>null</code> for all services.
+ * @param filterstring The filter criteria.
+ * @param allservices True if the bundle called getAllServiceReferences.
+ * @return An array of <code>ServiceReference</code> objects or
+ * <code>null</code> if no services are registered which satisfy
+ * the search.
+ * @throws InvalidSyntaxException If <code>filter</code> contains an
+ * invalid filter string that cannot be parsed.
+ * @throws java.lang.IllegalStateException If this BundleContext is no
+ * longer valid.
+ */
+ public ServiceReferenceImpl[] getServiceReferences(BundleContextImpl context, String clazz, String filterstring, boolean allservices) throws InvalidSyntaxException {
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println((allservices ? "getAllServiceReferences(" : "getServiceReferences(") + clazz + ", \"" + filterstring + "\")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ if (clazz != null) {
+ try /* test for permission to get clazz */{
+ checkGetServicePermission(clazz);
+ } catch (SecurityException se) {
+ return null;
+ }
+ }
+ Filter filter = (filterstring == null) ? null : context.createFilter(filterstring);
+ List references = null;
+ synchronized (this) {
+ references = lookupServiceReferences(clazz, filter);
+ Iterator iter = references.iterator();
+ while (iter.hasNext()) {
+ ServiceReferenceImpl reference = (ServiceReferenceImpl) iter.next();
+ if (allservices || isAssignableTo(context, reference)) {
+ if (clazz == null) {
+ try { /* test for permission to the classes */
+ checkGetServicePermission(reference.getClasses());
+ } catch (SecurityException se) {
+ iter.remove();
+ }
+ }
+ } else {
+ iter.remove();
+ }
+ }
+ }
+
+ int size = references.size();
+ if (size == 0) {
+ return null;
+ }
+ return (ServiceReferenceImpl[]) references.toArray(new ServiceReferenceImpl[size]);
+ }
+
+ /**
+ * Returns a <code>ServiceReference</code> object for a service that
+ * implements and was registered under the specified class.
+ *
+ * <p>
+ * This <code>ServiceReference</code> object is valid at the time of the
+ * call to this method, however as the Framework is a very dynamic
+ * environment, services can be modified or unregistered at anytime.
+ *
+ * <p>
+ * This method is the same as calling
+ * {@link BundleContext#getServiceReferences(String, String)} with a
+ * <code>null</code> filter string. It is provided as a convenience for
+ * when the caller is interested in any service that implements the
+ * specified class.
+ * <p>
+ * If multiple such services exist, the service with the highest ranking (as
+ * specified in its {@link Constants#SERVICE_RANKING} property) is returned.
+ * <p>
+ * If there is a tie in ranking, the service with the lowest service ID (as
+ * specified in its {@link Constants#SERVICE_ID} property); that is, the
+ * service that was registered first is returned.
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @param clazz The class name with which the service was registered.
+ * @return A <code>ServiceReference</code> object, or <code>null</code>
+ * if no services are registered which implement the named class.
+ * @throws java.lang.IllegalStateException If this BundleContext is no
+ * longer valid.
+ * @see #getServiceReferences(String, String)
+ */
+ public ServiceReferenceImpl getServiceReference(BundleContextImpl context, String clazz) {
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println("getServiceReference(" + clazz + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ try {
+ ServiceReferenceImpl[] references = getServiceReferences(context, clazz, null, false);
+
+ if (references != null) {
+ int index = 0;
+
+ int length = references.length;
+
+ if (length > 1) /* if more than one service, select highest ranking */{
+ int rankings[] = new int[length];
+ int count = 0;
+ int maxRanking = Integer.MIN_VALUE;
+
+ for (int i = 0; i < length; i++) {
+ int ranking = references[i].getRanking();
+
+ rankings[i] = ranking;
+
+ if (ranking > maxRanking) {
+ index = i;
+ maxRanking = ranking;
+ count = 1;
+ } else {
+ if (ranking == maxRanking) {
+ count++;
+ }
+ }
+ }
+
+ if (count > 1) /* if still more than one service, select lowest id */{
+ long minId = Long.MAX_VALUE;
+
+ for (int i = 0; i < length; i++) {
+ if (rankings[i] == maxRanking) {
+ long id = references[i].getId();
+
+ if (id < minId) {
+ index = i;
+ minId = id;
+ }
+ }
+ }
+ }
+ }
+
+ return references[index];
+ }
+ } catch (InvalidSyntaxException e) {
+ if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
+ Debug.println("InvalidSyntaxException w/ null filter" + e.getMessage()); //$NON-NLS-1$
+ Debug.printStackTrace(e);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the specified service object for a service.
+ * <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
+ * {@link #ungetService(ServiceReference)} the context bundle's use count
+ * for that service 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.
+ *
+ * <p>
+ * This method will always return <code>null</code> when the service
+ * associated with this <code>reference</code> has been unregistered.
+ *
+ * <p>
+ * The following steps are required to get the service object:
+ * <ol>
+ * <li>If the service has been unregistered, <code>null</code> is
+ * returned.
+ * <li>The context bundle's use count for this service is incremented by
+ * one.
+ * <li>If the context bundle's use count for the service is currently one
+ * and the service was registered with an object implementing the
+ * <code>ServiceFactory</code> interface, the
+ * {@link ServiceFactory#getService(Bundle, ServiceRegistration)} method is
+ * called to create a service object for the context bundle. 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. <br>
+ * If the service object returned by the <code>ServiceFactory</code>
+ * object is not an <code>instanceof</code> all the classes named when the
+ * service was registered or the <code>ServiceFactory</code> object throws
+ * an exception, <code>null</code> is returned and a Framework event of
+ * type {@link FrameworkEvent#ERROR} containing a {@link ServiceException}
+ * describing the error is fired.
+ * <li>The service object for the service is returned.
+ * </ol>
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @param reference A reference to the service.
+ * @return A service object for the service associated with
+ * <code>reference</code> or <code>null</code> if the service is
+ * not registered, the service object returned by a
+ * <code>ServiceFactory</code> does not implement the classes
+ * under which it was registered or the <code>ServiceFactory</code>
+ * threw an exception.
+ * @throws java.lang.SecurityException If the caller does not have the
+ * <code>ServicePermission</code> 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 java.lang.IllegalStateException If this BundleContext is no
+ * longer valid.
+ * @see #ungetService(ServiceReference)
+ * @see ServiceFactory
+ */
+ public Object getService(BundleContextImpl context, ServiceReferenceImpl reference) {
+ ServiceRegistrationImpl registration = reference.getRegistration();
+
+ checkGetServicePermission(registration.getClasses());
+
+ return registration.getService(context);
+ }
+
+ /**
+ * Releases the service object referenced by the specified
+ * <code>ServiceReference</code> object. If the context bundle's use count
+ * for the service is zero, this method returns <code>false</code>.
+ * Otherwise, the context bundle's use count for the service 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.
+ *
+ * <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</code> is returned.
+ * <li>The context bundle's use count for this service is decremented by
+ * one.
+ * <li>If the context bundle's use count for the service is currently zero
+ * and the service was registered with a <code>ServiceFactory</code>
+ * object, the
+ * {@link ServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
+ * method is called to release the service object for the context bundle.
+ * <li><code>true</code> is returned.
+ * </ol>
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @param reference A reference to the service to be released.
+ * @return <code>false</code> if the context bundle's use count for the
+ * service is zero or if the service has been unregistered;
+ * <code>true</code> otherwise.
+ * @throws java.lang.IllegalStateException If this BundleContext is no
+ * longer valid.
+ * @see #getService
+ * @see ServiceFactory
+ */
+ public boolean ungetService(BundleContextImpl context, ServiceReferenceImpl reference) {
+ ServiceRegistrationImpl registration = reference.getRegistration();
+
+ return registration.ungetService(context);
+ }
+
+ /**
+ * Returns this bundle's <code>ServiceReference</code> list for all
+ * services it has registered or <code>null</code> if this bundle has no
+ * registered services.
+ *
+ * <p>
+ * If the Java runtime supports permissions, a <code>ServiceReference</code>
+ * object to a service is included in the returned list only if the caller
+ * has the <code>ServicePermission</code> to get the service using at
+ * least one of the named classes the service was registered under.
+ *
+ * <p>
+ * The list is valid at the time of the call to this method, however, as the
+ * Framework is a very dynamic environment, services can be modified or
+ * unregistered at anytime.
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @return An array of <code>ServiceReference</code> objects or
+ * <code>null</code>.
+ * @throws java.lang.IllegalStateException If this bundle has been
+ * uninstalled.
+ * @see ServiceRegistration
+ * @see ServiceReference
+ * @see ServicePermission
+ */
+ public synchronized ServiceReferenceImpl[] getRegisteredServices(BundleContextImpl context) {
+ List references = lookupServiceReferences(context);
+ ListIterator iter = references.listIterator();
+ while (iter.hasNext()) {
+ ServiceReferenceImpl reference = (ServiceReferenceImpl) iter.next();
+ try { /* test for permission to the classes */
+ checkGetServicePermission(reference.getClasses());
+ } catch (SecurityException se) {
+ iter.remove();
+ }
+ }
+
+ int size = references.size();
+ if (size == 0) {
+ return null;
+ }
+ return (ServiceReferenceImpl[]) references.toArray(new ServiceReferenceImpl[size]);
+ }
+
+ /**
+ * Returns this bundle's <code>ServiceReference</code> list for all
+ * services it is using or returns <code>null</code> 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.
+ *
+ * <p>
+ * If the Java Runtime Environment supports permissions, a
+ * <code>ServiceReference</code> object to a service is included in the
+ * returned list only if the caller has the <code>ServicePermission</code>
+ * to get the service using at least one of the named classes the service
+ * was registered under.
+ * <p>
+ * The list is valid at the time of the call to this method, however, as the
+ * Framework is a very dynamic environment, services can be modified or
+ * unregistered at anytime.
+ *
+ * @param context The BundleContext of the requesting bundle.
+ * @return An array of <code>ServiceReference</code> objects or
+ * <code>null</code>.
+ * @throws java.lang.IllegalStateException If this bundle has been
+ * uninstalled.
+ * @see ServiceReference
+ * @see ServicePermission
+ */
+ public ServiceReferenceImpl[] getServicesInUse(BundleContextImpl context) {
+ Map servicesInUse = context.getServicesInUseMap();
+ if (servicesInUse == null) {
+ return null;
+ }
+ synchronized (servicesInUse) {
+ int size = servicesInUse.size();
+
+ if (size == 0) {
+ return null;
+ }
+
+ ServiceReferenceImpl[] references = new ServiceReferenceImpl[size];
+ int refcount = 0;
+
+ Iterator regsIter = servicesInUse.keySet().iterator();
+
+ for (int i = 0; i < size; i++) {
+ ServiceRegistrationImpl registration = (ServiceRegistrationImpl) regsIter.next();
+
+ try {
+ checkGetServicePermission(registration.getClasses());
+ } catch (SecurityException se) {
+ continue;
+ }
+
+ references[refcount] = registration.getReferenceImpl();
+ refcount++;
+ }
+
+ if (refcount < size) {
+ if (refcount == 0) {
+ return null;
+ }
+
+ ServiceReferenceImpl[] refs = references;
+ references = new ServiceReferenceImpl[refcount];
+
+ System.arraycopy(refs, 0, references, 0, refcount);
+ }
+
+ return references;
+ }
+ }
+
+ /**
+ * Called when the BundleContext is closing to unregister all services
+ * currently registered by the bundle.
+ *
+ * @param context The BundleContext of the closing bundle.
+ */
+ public void unregisterServices(BundleContextImpl context) {
+ List registrations;
+ synchronized (this) {
+ registrations = lookupServiceRegistrations(context);
+ }
+ ListIterator iter = registrations.listIterator();
+ while (iter.hasNext()) {
+ ServiceRegistrationImpl registration = (ServiceRegistrationImpl) iter.next();
+ try {
+ registration.unregister();
+ } catch (IllegalStateException e) {
+ /* already unregistered */
+ }
+ }
+ }
+
+ /**
+ * Called when the BundleContext is closing to unget all services
+ * currently used by the bundle.
+ *
+ * @param context The BundleContext of the closing bundle.
+ */
+ public void releaseServicesInUse(BundleContextImpl context) {
+ Map servicesInUse = context.getServicesInUseMap();
+ if (servicesInUse == null) {
+ return;
+ }
+ int usedSize;
+ ServiceRegistrationImpl[] usedServices;
+ synchronized (servicesInUse) {
+ usedSize = servicesInUse.size();
+ if (usedSize == 0) {
+ return;
+ }
+
+ if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
+ Debug.println("Releasing services"); //$NON-NLS-1$
+ }
+
+ usedServices = (ServiceRegistrationImpl[]) servicesInUse.keySet().toArray(new ServiceRegistrationImpl[usedSize]);
+ }
+
+ for (int i = 0; i < usedSize; i++) {
+ usedServices[i].releaseService(context);
+ }
+ }
+
+ /**
+ * Return the next available service id.
+ *
+ * @return next service id.
+ */
+ /* @GuardedBy("this") */
+ long getNextServiceId() {
+ long id = serviceid;
+ serviceid++;
+ return id;
+ }
+
+ /**
+ * Add the ServiceRegistrationImpl to the data structure.
+ *
+ * @param context The BundleContext of the bundle registering the service.
+ * @param registration The new ServiceRegistration.
+ */
+ /* @GuardedBy("this") */
+ void addServiceRegistration(BundleContextImpl context, ServiceRegistrationImpl registration) {
+ // Add the ServiceRegistration to the list of Services published by BundleContext.
+ ArrayList contextServices = (ArrayList) publishedServicesByContext.get(context);
+ if (contextServices == null) {
+ contextServices = new ArrayList(10);
+ publishedServicesByContext.put(context, contextServices);
+ }
+ contextServices.add(registration);
+
+ // Add the ServiceRegistration to the list of Services published by Class Name.
+ String[] clazzes = registration.getClasses();
+ int size = clazzes.length;
+
+ for (int i = 0; i < size; i++) {
+ String clazz = clazzes[i];
+
+ ArrayList services = (ArrayList) publishedServicesByClass.get(clazz);
+
+ if (services == null) {
+ services = new ArrayList(10);
+ publishedServicesByClass.put(clazz, services);
+ }
+
+ services.add(registration);
+ }
+
+ // Add the ServiceRegistration to the list of all published Services.
+ allPublishedServices.add(registration);
+ }
+
+ /**
+ * Remove the ServiceRegistrationImpl from the data structure.
+ *
+ * @param context The BundleContext of the bundle registering the service.
+ * @param registration The ServiceRegistration to remove.
+ */
+ /* @GuardedBy("this") */
+ void removeServiceRegistration(BundleContextImpl context, ServiceRegistrationImpl serviceReg) {
+ // Remove the ServiceRegistration from the list of Services published by BundleContext.
+ ArrayList contextServices = (ArrayList) publishedServicesByContext.get(context);
+ if (contextServices != null) {
+ contextServices.remove(serviceReg);
+ }
+
+ // Remove the ServiceRegistration from the list of Services published by Class Name.
+ String[] clazzes = serviceReg.getClasses();
+ int size = clazzes.length;
+
+ for (int i = 0; i < size; i++) {
+ String clazz = clazzes[i];
+ ArrayList services = (ArrayList) publishedServicesByClass.get(clazz);
+ services.remove(serviceReg);
+ }
+
+ // Remove the ServiceRegistration from the list of all published Services.
+ allPublishedServices.remove(serviceReg);
+ }
+
+ /**
+ * Lookup Service References in the data structure by class name and filter.
+ *
+ * @param clazz The class name with which the service was registered or
+ * <code>null</code> for all services.
+ * @param filter The filter criteria.
+ */
+ /* @GuardedBy("this") */
+ private List lookupServiceReferences(String clazz, Filter filter) {
+ ArrayList result;
+ if (clazz == null) { /* all services */
+ result = allPublishedServices;
+ } else {
+ /* services registered under the class name */
+ result = (ArrayList) publishedServicesByClass.get(clazz);
+ if (result == null) {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ result = new ArrayList(result); /* make a new list since we don't want to change the real list */
+
+ ListIterator iter = result.listIterator();
+ while (iter.hasNext()) {
+ ServiceRegistrationImpl registration = (ServiceRegistrationImpl) iter.next();
+ ServiceReferenceImpl reference = registration.getReferenceImpl();
+ if ((filter == null) || filter.match(reference)) {
+ iter.set(reference); /* replace the registration with its reference */
+ } else {
+ iter.remove();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Lookup Service Registrations in the data structure by BundleContext.
+ *
+ * @param context The BundleContext for which to return Service Registrations.
+ */
+ /* @GuardedBy("this") */
+ private List lookupServiceRegistrations(BundleContextImpl context) {
+ ArrayList result = (ArrayList) publishedServicesByContext.get(context);
+
+ if (result == null) {
+ return Collections.EMPTY_LIST;
+ }
+
+ result = new ArrayList(result); /* make a new list since we don't want to change the real list */
+ return result;
+ }
+
+ /**
+ * Lookup Service References in the data structure by BundleContext.
+ *
+ * @param context The BundleContext for which to return Service References.
+ */
+ /* @GuardedBy("this") */
+ private List lookupServiceReferences(BundleContextImpl context) {
+ List result = lookupServiceRegistrations(context);
+
+ ListIterator iter = result.listIterator();
+ while (iter.hasNext()) {
+ ServiceRegistrationImpl registration = (ServiceRegistrationImpl) iter.next();
+ ServiceReferenceImpl reference = registration.getReferenceImpl();
+ iter.set(reference); /* replace the registration with its reference */
+ }
+ return result;
+ }
+
+ /**
+ * Check for permission to register a service.
+ *
+ * The caller must have permission for ALL names.
+ */
+ private static void checkRegisterServicePermission(String[] names) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ int len = names.length;
+ for (int i = 0; i < len; i++) {
+ sm.checkPermission(new ServicePermission(names[i], ServicePermission.REGISTER));
+ }
+ }
+ }
+
+ /**
+ * Check for permission to get a service.
+ */
+ private static void checkGetServicePermission(String name) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new ServicePermission(name, ServicePermission.GET));
+ }
+ }
+
+ /**
+ * Check for permission to get a service.
+ *
+ * The caller must have permission for at least ONE name.
+ */
+ private static void checkGetServicePermission(String[] names) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ SecurityException se = null;
+ int len = names.length;
+ for (int i = 0; i < len; i++) {
+ try {
+ sm.checkPermission(new ServicePermission(names[i], ServicePermission.GET));
+ return;
+ } catch (SecurityException e) {
+ se = e;
+ }
+ }
+ throw se;
+ }
+ }
+
+ /**
+ * Check for permission to listen to a service.
+ */
+ static boolean hasListenServicePermission(ServiceEvent event, BundleContextImpl context) {
+ ProtectionDomain domain = context.getBundleImpl().getProtectionDomain();
+ if (domain == null) {
+ return true;
+ }
+
+ ServiceReferenceImpl reference = (ServiceReferenceImpl) event.getServiceReference();
+ String[] names = reference.getClasses();
+ int len = names.length;
+ for (int i = 0; i < len; i++) {
+ if (domain.implies(new ServicePermission(names[i], ServicePermission.GET))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return the name of the class that is not satisfied by the service object.
+ * @param clazzes Array of class names.
+ * @param serviceObject Service object.
+ * @return The name of the class that is not satisfied by the service object.
+ */
+ static String checkServiceClass(final String[] clazzes, final Object serviceObject) {
+ ClassLoader cl = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return serviceObject.getClass().getClassLoader();
+ }
+ });
+ for (int i = 0; i < clazzes.length; i++) {
+ try {
+ Class serviceClazz = cl == null ? Class.forName(clazzes[i]) : cl.loadClass(clazzes[i]);
+ if (!serviceClazz.isInstance(serviceObject))
+ return clazzes[i];
+ } catch (ClassNotFoundException e) {
+ //This check is rarely done
+ if (extensiveCheckServiceClass(clazzes[i], serviceObject.getClass()))
+ return clazzes[i];
+ }
+ }
+ return null;
+ }
+
+ private static boolean extensiveCheckServiceClass(String clazz, Class serviceClazz) {
+ if (clazz.equals(serviceClazz.getName()))
+ return false;
+ Class[] interfaces = serviceClazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ if (!extensiveCheckServiceClass(clazz, interfaces[i]))
+ return false;
+ Class superClazz = serviceClazz.getSuperclass();
+ if (superClazz != null)
+ if (!extensiveCheckServiceClass(clazz, superClazz))
+ return false;
+ return true;
+ }
+
+ static boolean isAssignableTo(BundleContextImpl context, ServiceReferenceImpl reference) {
+ if (!scopeEvents)
+ return true;
+ Bundle bundle = context.getBundleImpl();
+ String[] clazzes = reference.getClasses();
+ for (int i = 0; i < clazzes.length; i++)
+ if (!reference.isAssignableTo(bundle, clazzes[i]))
+ return false;
+ return true;
+ }
+}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceUse.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java
index 85f14065c..8e297527f 100644..100755
--- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/ServiceUse.java
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java
@@ -9,11 +9,13 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.osgi.framework.internal.core;
+package org.eclipse.osgi.internal.serviceregistry;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.eclipse.osgi.framework.debug.Debug;
+import org.eclipse.osgi.framework.internal.core.BundleContextImpl;
+import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
@@ -21,6 +23,8 @@ import org.osgi.framework.*;
* This class represents the use of a service by a bundle. One is created for each
* service acquired by a bundle. This class manages the calls to ServiceFactory
* and the bundle's use count.
+ *
+ * @ThreadSafe
*/
public class ServiceUse {
@@ -50,12 +54,9 @@ public class ServiceUse {
* @param context bundle getting the service
* @param registration ServiceRegistration of the service
*/
- protected ServiceUse(BundleContextImpl context, ServiceRegistrationImpl registration) {
- this.context = context;
- this.registration = registration;
+ ServiceUse(BundleContextImpl context, ServiceRegistrationImpl registration) {
this.useCount = 0;
-
- Object service = registration.service;
+ Object service = registration.getService();
if (service instanceof ServiceFactory) {
this.factory = (ServiceFactory) service;
this.cachedService = null;
@@ -63,6 +64,8 @@ public class ServiceUse {
this.factory = null;
this.cachedService = service;
}
+ this.context = context;
+ this.registration = registration;
}
/**
@@ -101,20 +104,20 @@ public class ServiceUse {
* reference.
*/
/* @GuardedBy("this") */
- protected Object getService() {
+ Object getService() {
if ((useCount > 0) || (factory == null)) {
useCount++;
return cachedService;
}
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("getService[factory=" + registration.context.bundle + "](" + context.bundle + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ Debug.println("getService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
final Object service;
try {
service = AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- return factory.getService(context.bundle, registration);
+ return factory.getService(context.getBundleImpl(), registration);
}
});
} catch (Throwable t) {
@@ -123,9 +126,9 @@ public class ServiceUse {
Debug.printStackTrace(t);
}
// allow the adaptor to handle this unexpected error
- context.framework.adaptor.handleRuntimeError(t);
+ context.getFramework().getAdaptor().handleRuntimeError(t);
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "getService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.context.bundle, se);
+ context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
return null;
}
@@ -135,18 +138,18 @@ public class ServiceUse {
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_OBJECT_NULL_EXCEPTION, factory.getClass().getName()), ServiceException.FACTORY_ERROR);
- context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.context.bundle, se);
+ context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
return null;
}
- String[] clazzes = registration.clazzes;
- String invalidService = BundleContextImpl.checkServiceClass(clazzes, service);
+ String[] clazzes = registration.getClasses();
+ String invalidService = ServiceRegistry.checkServiceClass(clazzes, service);
if (invalidService != null) {
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
Debug.println("Service object is not an instanceof " + invalidService); //$NON-NLS-1$
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_NOT_INSTANCEOF_CLASS_EXCEPTION, factory.getClass().getName(), invalidService), ServiceException.FACTORY_ERROR);
- context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.context.bundle, se);
+ context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
return null;
}
@@ -185,7 +188,7 @@ public class ServiceUse {
* is zero otherwise <code>false</code>.
*/
/* @GuardedBy("this") */
- protected boolean ungetService() {
+ boolean ungetService() {
if (useCount == 0) {
return true;
}
@@ -203,12 +206,12 @@ public class ServiceUse {
cachedService = null;
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("ungetService[factory=" + registration.context.bundle + "](" + context.bundle + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ Debug.println("ungetService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
try {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- factory.ungetService(context.bundle, registration, service);
+ factory.ungetService(context.getBundleImpl(), registration, service);
return null;
}
});
@@ -219,7 +222,7 @@ public class ServiceUse {
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.context.bundle, se);
+ context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
}
return true;
@@ -235,7 +238,7 @@ public class ServiceUse {
* </ol>
*/
/* @GuardedBy("this") */
- protected void releaseService() {
+ void releaseService() {
if ((useCount == 0) || (factory == null)) {
return;
}
@@ -244,12 +247,12 @@ public class ServiceUse {
useCount = 0;
if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
- Debug.println("releaseService[factory=" + registration.context.bundle + "](" + context.bundle + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ Debug.println("releaseService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
try {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- factory.ungetService(context.bundle, registration, service);
+ factory.ungetService(context.getBundleImpl(), registration, service);
return null;
}
});
@@ -260,7 +263,7 @@ public class ServiceUse {
}
ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, factory.getClass().getName(), "ungetService"), ServiceException.FACTORY_EXCEPTION, t); //$NON-NLS-1$
- context.framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.context.bundle, se);
+ context.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se);
}
}
}
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java
new file mode 100644
index 000000000..7fb7e5c6f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.osgi.internal.serviceregistry;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A Shrinkable Collection. This class provides a wrapper for a collection
+ * that allows items to be removed from the wrapped collection (shrinking) but
+ * does not allow items to be added to the wrapped collection.
+ *
+ * <p>
+ * All the optional <code>Collection</code> operations except
+ * <code>add</code> and <code>addAll</code> are supported. Attempting to add to the
+ * collection will result in an <code>UnsupportedOperationException</code>.
+ *
+ */
+
+public class ShrinkableCollection implements Collection {
+ private final Collection collection;
+
+ public ShrinkableCollection(Collection c) {
+ if (c == null) {
+ throw new NullPointerException();
+ }
+ collection = c;
+ }
+
+ public boolean add(Object var0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection var0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear() {
+ collection.clear();
+ }
+
+ public boolean contains(Object var0) {
+ return collection.contains(var0);
+ }
+
+ public boolean containsAll(Collection var0) {
+ return collection.containsAll(var0);
+ }
+
+ public boolean isEmpty() {
+ return collection.isEmpty();
+ }
+
+ public Iterator iterator() {
+ return collection.iterator();
+ }
+
+ public boolean remove(Object var0) {
+ return collection.remove(var0);
+ }
+
+ public boolean removeAll(Collection var0) {
+ return collection.removeAll(var0);
+ }
+
+ public boolean retainAll(Collection var0) {
+ return collection.retainAll(var0);
+ }
+
+ public int size() {
+ return collection.size();
+ }
+
+ public Object[] toArray() {
+ return collection.toArray();
+ }
+
+ public Object[] toArray(Object[] var0) {
+ return collection.toArray(var0);
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java
index dda20ec55..4ecb79a74 100644
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java
+++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/BaseAdaptor.java
@@ -20,8 +20,8 @@ import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.baseadaptor.hooks.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
-import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.internal.core.Constants;
+import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.baseadaptor.*;
@@ -78,7 +78,6 @@ public class BaseAdaptor implements FrameworkAdaptor {
}
private EventPublisher eventPublisher;
- private ServiceRegistry serviceRegistry;
private boolean stopping;
private HookRegistry hookRegistry;
private FrameworkLog log;
@@ -109,8 +108,6 @@ public class BaseAdaptor implements FrameworkAdaptor {
*/
public void initialize(EventPublisher publisher) {
this.eventPublisher = publisher;
- serviceRegistry = new ServiceRegistryImpl();
- ((ServiceRegistryImpl) serviceRegistry).initialize();
// set the adaptor for the adaptor hooks
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
@@ -239,13 +236,6 @@ public class BaseAdaptor implements FrameworkAdaptor {
}
/**
- * @see FrameworkAdaptor#getServiceRegistry()
- */
- public ServiceRegistry getServiceRegistry() {
- return serviceRegistry;
- }
-
- /**
* This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStart(BundleContext)} methods.
* @see FrameworkAdaptor#frameworkStart(BundleContext)
*/
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ServiceRegistryImpl.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ServiceRegistryImpl.java
deleted file mode 100644
index 1663b5a9a..000000000
--- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/framework/internal/core/ServiceRegistryImpl.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004, 2006 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
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.osgi.framework.internal.core;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import org.osgi.framework.*;
-
-/**
- * A default implementation of the ServiceRegistry.
- */
-public class ServiceRegistryImpl implements org.eclipse.osgi.framework.adaptor.ServiceRegistry {
-
- /** Published services by class name. Key is a String class name; Value is a ArrayList of ServiceRegistrations */
- protected HashMap publishedServicesByClass;
- /** All published services. Value is ServiceRegistrations */
- protected ArrayList allPublishedServices;
- /** Published services by BundleContext. Key is a BundleContext; Value is a ArrayList of ServiceRegistrations*/
- protected HashMap publishedServicesByContext;
-
- /**
- * Initializes the internal data structures of this ServiceRegistry.
- *
- */
- public void initialize() {
- publishedServicesByClass = new HashMap(50);
- publishedServicesByContext = new HashMap(50);
- allPublishedServices = new ArrayList(50);
- }
-
- /**
- * @see org.eclipse.osgi.framework.adaptor.ServiceRegistry#publishService(BundleContext, ServiceRegistration)
- */
- public void publishService(BundleContext context, ServiceRegistration serviceReg) {
-
- // Add the ServiceRegistration to the list of Services published by BundleContext.
- ArrayList contextServices = (ArrayList) publishedServicesByContext.get(context);
- if (contextServices == null) {
- contextServices = new ArrayList(10);
- publishedServicesByContext.put(context, contextServices);
- }
- contextServices.add(serviceReg);
-
- // Add the ServiceRegistration to the list of Services published by Class Name.
- String[] clazzes = ((ServiceRegistrationImpl) serviceReg).clazzes;
- int size = clazzes.length;
-
- for (int i = 0; i < size; i++) {
- String clazz = clazzes[i];
-
- ArrayList services = (ArrayList) publishedServicesByClass.get(clazz);
-
- if (services == null) {
- services = new ArrayList(10);
- publishedServicesByClass.put(clazz, services);
- }
-
- services.add(serviceReg);
- }
-
- // Add the ServiceRegistration to the list of all published Services.
- allPublishedServices.add(serviceReg);
- }
-
- /**
- * @see org.eclipse.osgi.framework.adaptor.ServiceRegistry#unpublishService(BundleContext, ServiceRegistration)
- */
- public void unpublishService(BundleContext context, ServiceRegistration serviceReg) {
-
- // Remove the ServiceRegistration from the list of Services published by BundleContext.
- ArrayList contextServices = (ArrayList) publishedServicesByContext.get(context);
- if (contextServices != null) {
- contextServices.remove(serviceReg);
- }
-
- // Remove the ServiceRegistration from the list of Services published by Class Name.
- String[] clazzes = ((ServiceRegistrationImpl) serviceReg).clazzes;
- int size = clazzes.length;
-
- for (int i = 0; i < size; i++) {
- String clazz = clazzes[i];
- ArrayList services = (ArrayList) publishedServicesByClass.get(clazz);
- services.remove(serviceReg);
- }
-
- // Remove the ServiceRegistration from the list of all published Services.
- allPublishedServices.remove(serviceReg);
-
- }
-
- /**
- * @see org.eclipse.osgi.framework.adaptor.ServiceRegistry#unpublishServices(BundleContext)
- */
- public void unpublishServices(BundleContext context) {
- // Get all the Services published by the BundleContext.
- ArrayList serviceRegs = (ArrayList) publishedServicesByContext.get(context);
- if (serviceRegs != null) {
- // Remove this list for the BundleContext
- publishedServicesByContext.remove(context);
- int size = serviceRegs.size();
- for (int i = 0; i < size; i++) {
- ServiceRegistrationImpl serviceReg = (ServiceRegistrationImpl) serviceRegs.get(i);
- // Remove each service from the list of all published Services
- allPublishedServices.remove(serviceReg);
-
- // Remove each service from the list of Services published by Class Name.
- String[] clazzes = serviceReg.clazzes;
- int numclazzes = clazzes.length;
-
- for (int j = 0; j < numclazzes; j++) {
- String clazz = clazzes[j];
- ArrayList services = (ArrayList) publishedServicesByClass.get(clazz);
- services.remove(serviceReg);
- }
- }
- }
- }
-
- /**
- * @see org.eclipse.osgi.framework.adaptor.ServiceRegistry#lookupServiceReferences(String, Filter)
- */
- public ServiceReference[] lookupServiceReferences(String clazz, Filter filter) {
- int size;
- ArrayList references;
- ArrayList serviceRegs;
- if (clazz == null) /* all services */
- serviceRegs = allPublishedServices;
- else
- /* services registered under the class name */
- serviceRegs = (ArrayList) publishedServicesByClass.get(clazz);
-
- if (serviceRegs == null)
- return (null);
-
- size = serviceRegs.size();
-
- if (size == 0)
- return (null);
-
- references = new ArrayList(size);
- for (int i = 0; i < size; i++) {
- ServiceRegistration registration = (ServiceRegistration) serviceRegs.get(i);
-
- ServiceReference reference = registration.getReference();
- if ((filter == null) || filter.match(reference)) {
- references.add(reference);
- }
- }
-
- if (references.size() == 0) {
- return null;
- }
-
- return (ServiceReference[]) references.toArray(new ServiceReference[references.size()]);
-
- }
-
- /**
- * @see org.eclipse.osgi.framework.adaptor.ServiceRegistry#lookupServiceReferences(BundleContext)
- */
- public ServiceReference[] lookupServiceReferences(BundleContext context) {
- int size;
- ArrayList references;
- ArrayList serviceRegs = (ArrayList) publishedServicesByContext.get(context);
-
- if (serviceRegs == null) {
- return (null);
- }
-
- size = serviceRegs.size();
-
- if (size == 0) {
- return (null);
- }
-
- references = new ArrayList(size);
- for (int i = 0; i < size; i++) {
- ServiceRegistration registration = (ServiceRegistration) serviceRegs.get(i);
-
- ServiceReference reference = registration.getReference();
- references.add(reference);
- }
-
- if (references.size() == 0) {
- return null;
- }
-
- return (ServiceReference[]) references.toArray(new ServiceReference[references.size()]);
- }
-
-}

Back to the top