diff options
author | BJ Hargrave | 2008-10-01 19:49:49 +0000 |
---|---|---|
committer | BJ Hargrave | 2008-10-01 19:49:49 +0000 |
commit | 19c51e86352d7f6ef6f0dd1c525ce14c118585e5 (patch) | |
tree | 48cdfce5479b2ec4eb26a005d96a90823e375a44 /bundles/org.eclipse.osgi/core/framework/org/eclipse | |
parent | be5cb5ffadb37eca2cf7fd201fe0b397d580c9cb (diff) | |
download | rt.equinox.framework-19c51e86352d7f6ef6f0dd1c525ce14c118585e5.tar.gz rt.equinox.framework-19c51e86352d7f6ef6f0dd1c525ce14c118585e5.tar.xz rt.equinox.framework-19c51e86352d7f6ef6f0dd1c525ce14c118585e5.zip |
ASSIGNED - bug 244625: Implement new service registry hooks (RFC 126)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=244625
Add FindHook support
Diffstat (limited to 'bundles/org.eclipse.osgi/core/framework/org/eclipse')
6 files changed, 278 insertions, 137 deletions
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 d401374f4..76b4c0a4c 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 @@ -210,7 +210,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 */ - serviceRegistry = new ServiceRegistry(); + serviceRegistry = new ServiceRegistry(this); // 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). 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 index 954e94b2f..345924288 100755 --- 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 @@ -188,7 +188,7 @@ public class ServiceReferenceImpl implements ServiceReference, Comparable { * {@link Constants#SERVICE_ID service id} and greater if it has a lower * service id. * - * @param reference The <code>ServiceReference</code> to be compared. + * @param object 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>. @@ -196,9 +196,7 @@ public class ServiceReferenceImpl implements ServiceReference, Comparable { */ 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; + return registration.compareTo(other.registration); } /** @@ -219,11 +217,11 @@ public class ServiceReferenceImpl implements ServiceReference, Comparable { */ public boolean equals(Object obj) { if (obj == this) { - return (true); + return true; } if (!(obj instanceof ServiceReferenceImpl)) { - return (false); + return false; } ServiceReferenceImpl other = (ServiceReferenceImpl) obj; @@ -257,22 +255,4 @@ public class ServiceReferenceImpl implements ServiceReference, Comparable { 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/internal/serviceregistry/ServiceRegistrationImpl.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java index 7a8db27f8..58e1a6f14 100755 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceRegistrationImpl.java @@ -34,7 +34,7 @@ import org.osgi.framework.Constants; * * @ThreadSafe */ -public class ServiceRegistrationImpl implements ServiceRegistration { +public class ServiceRegistrationImpl implements ServiceRegistration, Comparable { /** Internal framework object. */ private final Framework framework; @@ -56,17 +56,18 @@ public class ServiceRegistrationImpl implements ServiceRegistration { /* @GuardedBy("registrationLock") */ private ServiceReferenceImpl reference; - /** list of contexts using the service. */ + /** List of contexts using the service. + * List<BundleContextImpl>. + * */ /* @GuardedBy("registrationLock") */ - private ArrayList contextsUsing; + private List contextsUsing; /** properties for this registration. */ /* @GuardedBy("registrationLock") */ private ServiceProperties properties; /** service id. */ - /* @GuardedBy("registrationLock") */ - private long serviceid; + private final long serviceid; /** service ranking. */ /* @GuardedBy("registrationLock") */ @@ -94,7 +95,9 @@ public class ServiceRegistrationImpl implements ServiceRegistration { this.framework = context.getFramework(); this.clazzes = clazzes; /* must be set before calling createProperties. */ this.service = service; + synchronized (registrationLock) { + this.serviceid = registry.getNextServiceId(); /* must be set before calling createProperties. */ this.contextsUsing = null; /* We leak this from the constructor here, but it is ok * because the ServiceReferenceImpl constructor only @@ -114,7 +117,6 @@ public class ServiceRegistrationImpl implements ServiceRegistration { context.checkValid(); synchronized (registrationLock) { ref = reference; /* used to publish event outside sync */ - 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) { @@ -347,9 +349,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration { * @return The service id for this service. */ long getId() { - synchronized (registrationLock) { - return serviceid; - } + return serviceid; } /** @@ -366,7 +366,7 @@ public class ServiceRegistrationImpl implements ServiceRegistration { return clazzes; } - Object getService() { + Object getServiceObject() { return service; } @@ -596,4 +596,36 @@ public class ServiceRegistrationImpl implements ServiceRegistration { return sb.toString(); } + + /** + * Compares this <code>ServiceRegistrationImpl</code> with the specified + * <code>ServiceRegistrationImpl</code> for order. + * + * <p> + * If this <code>ServiceRegistrationImpl</code> and the specified + * <code>ServiceRegistrationImpl</code> have the same + * {@link Constants#SERVICE_ID service id} they are equal. This + * <code>ServiceRegistrationImpl</code> is less than the specified + * <code>ServiceRegistrationImpl</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>ServiceRegistrationImpl</code> + * and the specified <code>ServiceRegistrationImpl</code> have the same + * {@link Constants#SERVICE_RANKING service ranking}, this + * <code>ServiceRegistrationImpl</code> is less than the specified + * <code>ServiceRegistrationImpl</code> if it has a higher + * {@link Constants#SERVICE_ID service id} and greater if it has a lower + * service id. + * + * @param object The <code>ServiceRegistrationImpl</code> to be compared. + * @return Returns a negative integer, zero, or a positive integer if this + * <code>ServiceRegistrationImpl</code> is less than, equal to, or + * greater than the specified <code>ServiceRegistrationImpl</code>. + */ + public int compareTo(Object object) { + ServiceRegistrationImpl other = (ServiceRegistrationImpl) 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; + } } 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 index d159302d4..33bdad7d9 100755 --- 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 @@ -18,6 +18,7 @@ import org.eclipse.osgi.framework.internal.core.*; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; import org.osgi.framework.Constants; +import org.osgi.framework.hooks.service.FindHook; /** * The Service Registry. This class is the main control point for service @@ -29,26 +30,39 @@ 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 */ + /** Published services by class name. + * Map<String,List<ServiceRegistrationImpl>> + * The List<ServiceRegistrationImpl>s are sorted. + */ /* @GuardedBy("this") */ - private final HashMap/*<String,ArrayList<ServiceRegistrationImpl>>*/publishedServicesByClass; - /** All published services. Value is ServiceRegistrations */ + private final Map/*<String,List<ServiceRegistrationImpl>>*/publishedServicesByClass; + /** All published services. + * List<ServiceRegistrationImpl>. + * The List<ServiceRegistrationImpl> is sorted. + */ /* @GuardedBy("this") */ - private final ArrayList/*<ServiceRegistrationImpl>*/allPublishedServices; - /** Published services by BundleContext. Key is a BundleContext; Value is a ArrayList of ServiceRegistrations*/ + private final List/*<ServiceRegistrationImpl>*/allPublishedServices; + /** Published services by BundleContextImpl. + * Map<BundleContextImpl,List<ServiceRegistrationImpl>>. + * The List<ServiceRegistrationImpl>s are NOT sorted. + */ /* @GuardedBy("this") */ - private final HashMap/*<BundleContextImpl,ArrayList<ServiceRegistrationImpl>*/publishedServicesByContext; + private final Map/*<BundleContextImpl,List<ServiceRegistrationImpl>>*/publishedServicesByContext; /** next free service id. */ /* @GuardedBy("this") */ private long serviceid; /** initial capacity of the data structure */ private static final int initialCapacity = 50; + /** framework which created this service registry */ + private final Framework framework; + /** * Initializes the internal data structures of this ServiceRegistry. * */ - public ServiceRegistry() { + public ServiceRegistry(Framework framework) { + this.framework = framework; serviceid = 1; publishedServicesByClass = new HashMap(initialCapacity); publishedServicesByContext = new HashMap(initialCapacity); @@ -58,8 +72,8 @@ public class ServiceRegistry { /** * 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 + * <code>ServiceRegistrationImpl</code> object is returned. The + * <code>ServiceRegistrationImpl</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 @@ -106,7 +120,7 @@ public class ServiceRegistry { * 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 + * @return A <code>ServiceRegistrationImpl</code> object for use by the bundle * registering the service to update the service's properties or to * unregister the service. * @@ -174,12 +188,11 @@ public class ServiceRegistry { 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 + * Returns an array of <code>ServiceReferenceImpl</code> objects. The returned + * array of <code>ServiceReferenceImpl</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 @@ -203,19 +216,19 @@ public class ServiceRegistry { * * <p> * The following steps are required to select a set of - * <code>ServiceReference</code> objects: + * <code>ServiceReferenceImpl</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 + * is parsed and the set <code>ServiceReferenceImpl</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 + * <code>ServiceReferenceImpl</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> + * correct permission for a particular <code>ServiceReferenceImpl</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> @@ -227,12 +240,12 @@ public class ServiceRegistry { * <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 was registered. For any given <code>ServiceReferenceImpl</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 + * <code>ServiceReferenceImpl</code> objects. + * <li>An array of the remaining <code>ServiceReferenceImpl</code> objects is * returned. * </ol> * @@ -241,7 +254,7 @@ public class ServiceRegistry { * <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 + * @return An array of <code>ServiceReferenceImpl</code> objects or * <code>null</code> if no services are registered which satisfy * the search. * @throws InvalidSyntaxException If <code>filter</code> contains an @@ -261,9 +274,9 @@ public class ServiceRegistry { } } Filter filter = (filterstring == null) ? null : context.createFilter(filterstring); - List references = null; + List references; synchronized (this) { - references = lookupServiceReferences(clazz, filter); + references = changeRegistrationsToReferences(lookupServiceRegistrations(clazz, filter)); Iterator iter = references.iterator(); while (iter.hasNext()) { ServiceReferenceImpl reference = (ServiceReferenceImpl) iter.next(); @@ -281,6 +294,8 @@ public class ServiceRegistry { } } + processFindHooks(context, clazz, filterstring, allservices, references); + int size = references.size(); if (size == 0) { return null; @@ -328,48 +343,9 @@ public class ServiceRegistry { 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]; + // Since we maintain the registrations in a sorted List, the first element is always the + // correct one to return. + return references[0]; } } catch (InvalidSyntaxException e) { if (Debug.DEBUG && Debug.DEBUG_GENERAL) { @@ -517,7 +493,7 @@ public class ServiceRegistry { * @see ServicePermission */ public synchronized ServiceReferenceImpl[] getRegisteredServices(BundleContextImpl context) { - List references = lookupServiceReferences(context); + List references = changeRegistrationsToReferences(lookupServiceRegistrations(context)); ListIterator iter = references.listIterator(); while (iter.hasNext()) { ServiceReferenceImpl reference = (ServiceReferenceImpl) iter.next(); @@ -678,33 +654,39 @@ public class ServiceRegistry { */ /* @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); + // Add the ServiceRegistrationImpl to the list of Services published by BundleContextImpl. + List contextServices = (List) publishedServicesByContext.get(context); if (contextServices == null) { contextServices = new ArrayList(10); publishedServicesByContext.put(context, contextServices); } + // The list is NOT sorted, so we just add contextServices.add(registration); - // Add the ServiceRegistration to the list of Services published by Class Name. + // Add the ServiceRegistrationImpl to the list of Services published by Class Name. String[] clazzes = registration.getClasses(); int size = clazzes.length; + int insertIndex; for (int i = 0; i < size; i++) { String clazz = clazzes[i]; - ArrayList services = (ArrayList) publishedServicesByClass.get(clazz); + List services = (List) publishedServicesByClass.get(clazz); if (services == null) { services = new ArrayList(10); publishedServicesByClass.put(clazz, services); } - services.add(registration); + // The list is sorted, so we must find the proper location to insert + insertIndex = -Collections.binarySearch(services, registration) - 1; + services.add(insertIndex, registration); } - // Add the ServiceRegistration to the list of all published Services. - allPublishedServices.add(registration); + // Add the ServiceRegistrationImpl to the list of all published Services. + // The list is sorted, so we must find the proper location to insert + insertIndex = -Collections.binarySearch(allPublishedServices, registration) - 1; + allPublishedServices.add(insertIndex, registration); } /** @@ -715,55 +697,58 @@ public class ServiceRegistry { */ /* @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); + // Remove the ServiceRegistrationImpl from the list of Services published by BundleContextImpl. + List contextServices = (List) publishedServicesByContext.get(context); if (contextServices != null) { contextServices.remove(serviceReg); } - // Remove the ServiceRegistration from the list of Services published by Class Name. + // Remove the ServiceRegistrationImpl 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); + List services = (List) publishedServicesByClass.get(clazz); services.remove(serviceReg); } - // Remove the ServiceRegistration from the list of all published Services. + // Remove the ServiceRegistrationImpl from the list of all published Services. allPublishedServices.remove(serviceReg); } /** - * Lookup Service References in the data structure by class name and filter. + * Lookup Service Registrations 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. + * @return List<ServiceRegistrationImpl> */ /* @GuardedBy("this") */ - private List lookupServiceReferences(String clazz, Filter filter) { - ArrayList result; + private List lookupServiceRegistrations(String clazz, Filter filter) { + List 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 = (List) publishedServicesByClass.get(clazz); + } + + if ((result == null) || (result.size() == 0)) { + return Collections.EMPTY_LIST; } result = new ArrayList(result); /* make a new list since we don't want to change the real list */ + if (filter == null) { + return result; + } + 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 { + if (!filter.match(registration.getReferenceImpl())) { iter.remove(); } } @@ -774,33 +759,30 @@ public class ServiceRegistry { * Lookup Service Registrations in the data structure by BundleContext. * * @param context The BundleContext for which to return Service Registrations. + * @return List<ServiceRegistrationImpl> */ /* @GuardedBy("this") */ private List lookupServiceRegistrations(BundleContextImpl context) { - ArrayList result = (ArrayList) publishedServicesByContext.get(context); + List result = (List) publishedServicesByContext.get(context); - if (result == null) { + if ((result == null) || (result.size() == 0)) { return Collections.EMPTY_LIST; } - result = new ArrayList(result); /* make a new list since we don't want to change the real list */ - return result; + return new ArrayList(result); /* make a new list since we don't want to change the real list */ } /** - * Lookup Service References in the data structure by BundleContext. + * Modify a List<ServiceRegistrationImpl> to a List<ServiceReferenceImpl>. * - * @param context The BundleContext for which to return Service References. + * @param result The input List<ServiceRegistrationImpl>. + * @return List<ServiceReferenceImpl> */ - /* @GuardedBy("this") */ - private List lookupServiceReferences(BundleContextImpl context) { - List result = lookupServiceRegistrations(context); - + private static List changeRegistrationsToReferences(List result) { 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 */ + iter.set(registration.getReferenceImpl()); /* replace the registration with its reference */ } return result; } @@ -923,4 +905,61 @@ public class ServiceRegistry { return false; return true; } + + private static final String findHookName = FindHook.class.getName(); + + /** + * Call the registered FindHook services to allow them to inspect and possibly shrink the result. + * The FindHook must be called in order: descending by service.ranking, then ascending by service.id. + * This is the natural order for ServiceReference. + * + * @param context The context of the bundle getting the service references. + * @param clazz The class name used to search for the service references. + * @param filterstring The filter used to search for the service references. + * @param allservices True if getAllServiceReferences called. + * @param result The result to return to the caller which may have been shrunk by the FindHooks. + */ + private void processFindHooks(BundleContextImpl context, String clazz, String filterstring, boolean allservices, Collection result) { + BundleContextImpl systemBundleContext = framework.getSystemBundleContext(); + if (systemBundleContext == null) { // if no system bundle context, we are done! + return; + } + + if (Debug.DEBUG && Debug.DEBUG_SERVICES) { + Debug.println("processFindHook(" + context.getBundleImpl() + "," + clazz + "," + filterstring + "," + allservices + "," + result + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + } + + Collection references = new ShrinkableCollection(result); // prevent hooks from adding to result + List hooks; + synchronized (this) { + hooks = lookupServiceRegistrations(findHookName, null); + } + // Since the list is already sorted, we don't need to sort the list to call the hooks + // in the proper order. + + Iterator iter = hooks.iterator(); + while (iter.hasNext()) { + ServiceRegistrationImpl registration = (ServiceRegistrationImpl) iter.next(); + Object findHook = registration.getService(systemBundleContext); + if (findHook == null) { // if the hook is null + continue; + } + try { + if (findHook instanceof FindHook) { // if the hook is usable + ((FindHook) findHook).find(context, clazz, filterstring, allservices, references); + } + } catch (Throwable t) { + if (Debug.DEBUG && Debug.DEBUG_SERVICES) { + Debug.println(findHook + ".find() exception: " + t.getMessage()); //$NON-NLS-1$ + Debug.printStackTrace(t); + } + // allow the adaptor to handle this unexpected error + framework.getAdaptor().handleRuntimeError(t); + ServiceException se = new ServiceException(NLS.bind(Msg.SERVICE_FACTORY_EXCEPTION, findHook.getClass().getName(), "find"), t); //$NON-NLS-1$ + framework.publishFrameworkEvent(FrameworkEvent.ERROR, registration.getBundle(), se); + } finally { + registration.ungetService(systemBundleContext); + } + } + } } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java index 8e297527f..b67baf9b4 100755 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ServiceUse.java @@ -56,7 +56,7 @@ public class ServiceUse { */ ServiceUse(BundleContextImpl context, ServiceRegistrationImpl registration) { this.useCount = 0; - Object service = registration.getService(); + Object service = registration.getServiceObject(); if (service instanceof ServiceFactory) { this.factory = (ServiceFactory) service; this.cachedService = null; 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..cbc70ec7e --- /dev/null +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/internal/serviceregistry/ShrinkableCollection.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * 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; + + 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); + } +} |