Author: cziegeler Date: Mon Apr 27 07:12:18 2015 New Revision: 1676200 URL: http://svn.apache.org/r1676200 Log: FELIX-4866 : Improve service registry
Added: felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java (with props) Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java felix/trunk/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java felix/trunk/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Mon Apr 27 07:12:18 2015 @@ -3330,7 +3330,7 @@ public class Felix extends BundleImpl im // Invoke ListenerHook.removed() if filter updated. Set<ServiceReference<org.osgi.framework.hooks.service.ListenerHook>> listenerHooks = - m_registry.getHooks(org.osgi.framework.hooks.service.ListenerHook.class); + m_registry.getHookRegistry().getHooks(org.osgi.framework.hooks.service.ListenerHook.class); if (oldFilter != null) { final Collection removed = Collections.singleton( @@ -3401,7 +3401,7 @@ public class Felix extends BundleImpl im { // Invoke the ListenerHook.removed() on all hooks. Set<ServiceReference<org.osgi.framework.hooks.service.ListenerHook>> listenerHooks = - m_registry.getHooks(org.osgi.framework.hooks.service.ListenerHook.class); + m_registry.getHookRegistry().getHooks(org.osgi.framework.hooks.service.ListenerHook.class); Collection removed = Collections.singleton(listener); for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks) { @@ -3485,11 +3485,11 @@ public class Felix extends BundleImpl im } } - reg = m_registry.registerService(context, classNames, svcObj, dict); + reg = m_registry.registerService(context.getBundle(), classNames, svcObj, dict); // Check to see if this a listener hook; if so, then we need // to invoke the callback with all existing service listeners. - if (ServiceRegistry.isHook( + if (HookRegistry.isHook( classNames, org.osgi.framework.hooks.service.ListenerHook.class, svcObj)) { org.osgi.framework.hooks.service.ListenerHook lh = @@ -3509,13 +3509,12 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, reg.getReference(), null); + this.ungetService(this, reg.getReference(), null); } } } - // Fire service event. - fireServiceEvent(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()), null); + this.fireServiceEvent(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()), null); return reg; } @@ -3573,7 +3572,7 @@ public class Felix extends BundleImpl im // activate findhooks Set<ServiceReference<org.osgi.framework.hooks.service.FindHook>> findHooks = - m_registry.getHooks(org.osgi.framework.hooks.service.FindHook.class); + m_registry.getHookRegistry().getHooks(org.osgi.framework.hooks.service.FindHook.class); for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks) { org.osgi.framework.hooks.service.FindHook fh = getService(this, sr, false); @@ -3710,19 +3709,19 @@ public class Felix extends BundleImpl im // Hook service management methods. // - boolean isHookBlackListed(ServiceReference sr) + boolean isHookBlackListed(final ServiceReference sr) { - return m_registry.isHookBlackListed(sr); + return m_registry.getHookRegistry().isHookBlackListed(sr); } - void blackListHook(ServiceReference sr) + void blackListHook(final ServiceReference sr) { - m_registry.blackListHook(sr); + m_registry.getHookRegistry().blackListHook(sr); } - public <S> Set<ServiceReference<S>> getHooks(Class<S> hookClass) + public <S> Set<ServiceReference<S>> getHooks(final Class<S> hookClass) { - return m_registry.getHooks(hookClass); + return m_registry.getHookRegistry().getHooks(hookClass); } // Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java Mon Apr 27 07:12:18 2015 @@ -54,7 +54,7 @@ class FrameworkStartLevelImpl implements @SuppressWarnings("unchecked") void start() { - m_slReg = (ServiceRegistration<StartLevel>) m_registry.registerService(m_felix._getBundleContext(), + m_slReg = (ServiceRegistration<StartLevel>) m_registry.registerService(m_felix, new String[] { StartLevel.class.getName() }, new StartLevelImpl(m_felix), null); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java Mon Apr 27 07:12:18 2015 @@ -52,7 +52,7 @@ class FrameworkWiringImpl implements Fra @SuppressWarnings("unchecked") void start() { - m_paReg = (ServiceRegistration<PackageAdmin>) m_registry.registerService(m_felix._getBundleContext(), + m_paReg = (ServiceRegistration<PackageAdmin>) m_registry.registerService(m_felix, new String[] { PackageAdmin.class.getName() }, new PackageAdminImpl(m_felix), null); Added: felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java?rev=1676200&view=auto ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java (added) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java Mon Apr 27 07:12:18 2015 @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.framework; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.WeakHashMap; + +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceReference; + +/** + * This registry holds all services implementing one of the hook services + */ +public class HookRegistry +{ + /** no need to use a sync'ed structure as this is read only. */ + private final static Map<String, Class<?>> HOOK_CLASSES = new HashMap<String, Class<?>>(); + + static + { + addHookClass(org.osgi.framework.hooks.bundle.CollisionHook.class); + addHookClass(org.osgi.framework.hooks.bundle.FindHook.class); + addHookClass(org.osgi.framework.hooks.bundle.EventHook.class); + addHookClass(org.osgi.framework.hooks.service.EventHook.class); + addHookClass(org.osgi.framework.hooks.service.EventListenerHook.class); + addHookClass(org.osgi.framework.hooks.service.FindHook.class); + addHookClass(org.osgi.framework.hooks.service.ListenerHook.class); + addHookClass(org.osgi.framework.hooks.weaving.WeavingHook.class); + addHookClass(org.osgi.framework.hooks.weaving.WovenClassListener.class); + addHookClass(org.osgi.framework.hooks.resolver.ResolverHookFactory.class); + addHookClass(org.osgi.service.url.URLStreamHandlerService.class); + addHookClass(java.net.ContentHandler.class); + }; + + private static void addHookClass(final Class<?> c) { + HOOK_CLASSES.put(c.getName(), c); + } + + private final Map<String, Set<ServiceReference<?>>> m_allHooks = + new HashMap<String, Set<ServiceReference<?>>>(); + + private final WeakHashMap<ServiceReference<?>, ServiceReference<?>> m_blackList = + new WeakHashMap<ServiceReference<?>, ServiceReference<?>>(); + + + static boolean isHook(final String[] classNames, final Class<?> hookClass, final Object svcObj) + { + for (final String serviceName : classNames) + { + if (serviceName.equals(hookClass.getName())) + { + // For a service factory, we can only match names. + if (svcObj instanceof ServiceFactory) + { + return true; + } + // For a service object, check if its class matches. + if (hookClass.isAssignableFrom(svcObj.getClass())) + { + return true; + } + } + } + + return false; + } + + private boolean isHook(final String serviceName, final Object svcObj) + { + final Class<?> hookClass = HOOK_CLASSES.get(serviceName); + if ( hookClass != null ) + { + // For a service factory, we can only match names. + if (svcObj instanceof ServiceFactory) + { + return true; + } + // For a service object, check if its class matches. + if (hookClass.isAssignableFrom(svcObj.getClass())) + { + return true; + } + } + + return false; + } + + public void addHooks(final String[] classNames, final Object svcObj, final ServiceReference<?> ref) + { + for(final String serviceName : classNames) + { + if (isHook(serviceName, svcObj)) + { + synchronized (m_allHooks) + { + Set<ServiceReference<?>> hooks = m_allHooks.get(serviceName); + if (hooks == null) + { + hooks = new TreeSet<ServiceReference<?>>(Collections.reverseOrder()); + m_allHooks.put(serviceName, hooks); + } + hooks.add(ref); + } + } + } + } + + public void updateHooks(final ServiceReference<?> ref) + { + // We maintain the hooks sorted, so if ranking has changed for example, + // we need to ensure the order remains correct by resorting the hooks. + final Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref) + .getRegistration().getService(); + final String [] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS); + + for(final String serviceName : classNames) + { + if (isHook(serviceName, svcObj)) + { + synchronized (m_allHooks) + { + final Set<ServiceReference<?>> hooks = m_allHooks.get(serviceName); + if (hooks != null) + { + List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(hooks); + hooks.clear(); + hooks.addAll(refs); + } + } + } + } + } + + public void removeHooks(final ServiceReference<?> ref) + { + final Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref) + .getRegistration().getService(); + final String [] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS); + + for(final String serviceName : classNames) + { + if (isHook(serviceName, svcObj)) + { + synchronized (m_allHooks) + { + final Set<ServiceReference<?>> hooks = m_allHooks.get(serviceName); + if (hooks != null) + { + hooks.remove(ref); + if (hooks.isEmpty()) + { + m_allHooks.remove(serviceName); + } + } + } + } + } + m_blackList.remove(ref); + } + + public <S> Set<ServiceReference<S>> getHooks(final Class<S> hookClass) + { + synchronized (m_allHooks) + { + final Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass.getName()); + if (hooks != null) + { + SortedSet<ServiceReference<?>> sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder()); + sorted.addAll(hooks); + return (Set) sorted; + } + return Collections.emptySet(); + } + } + + public boolean isHookBlackListed(final ServiceReference<?> sr) + { + return m_blackList.containsKey(sr); + } + + public void blackListHook(final ServiceReference<?> sr) + { + m_blackList.put(sr, sr); + } + +} Propchange: felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: felix/trunk/framework/src/main/java/org/apache/felix/framework/HookRegistry.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java Mon Apr 27 07:12:18 2015 @@ -66,6 +66,10 @@ class ServiceRegistrationImpl implements // Flag indicating that we are unregistering. private volatile boolean m_isUnregistering = false; + private volatile Thread lock; + + private final Object syncObject = new Object(); + public ServiceRegistrationImpl( ServiceRegistry registry, Bundle bundle, String[] classes, Long serviceId, @@ -753,4 +757,36 @@ class ServiceRegistrationImpl implements return Collections.EMPTY_SET; } } + + public boolean isLocked() + { + return this.lock == Thread.currentThread(); + } + + public void lock() + { + synchronized ( this.syncObject ) + { + while ( this.lock != null ) + { + try + { + this.syncObject.wait(); + } + catch ( final InterruptedException re) { + // nothing to do + } + } + this.lock = Thread.currentThread(); + } + } + + public void unlock() + { + synchronized ( this.syncObject ) + { + this.lock = null; + this.syncObject.notifyAll(); + } + } } \ No newline at end of file Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java Mon Apr 27 07:12:18 2015 @@ -22,90 +22,74 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; import org.apache.felix.framework.capabilityset.CapabilitySet; import org.apache.felix.framework.capabilityset.SimpleFilter; import org.apache.felix.framework.wiring.BundleCapabilityImpl; import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceException; -import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; +import org.osgi.resource.Capability; public class ServiceRegistry { private final Logger m_logger; - private long m_currentServiceId = 1L; + + /** Counter for the service id */ + private final AtomicLong m_currentServiceId = new AtomicLong(1); + // Maps bundle to an array of service registrations. - private final Map<Bundle, ServiceRegistration<?>[]> m_regsMap = Collections.synchronizedMap(new HashMap<Bundle, ServiceRegistration<?>[]>()); + private final ConcurrentMap<Bundle, List<ServiceRegistration<?>>> m_regsMap = new ConcurrentHashMap<Bundle, List<ServiceRegistration<?>>>(); + // Capability set for all service registrations. - private final CapabilitySet m_regCapSet; + private final CapabilitySet m_regCapSet = new CapabilitySet(Collections.singletonList(Constants.OBJECTCLASS), false); - // Maps registration to thread to keep track when a - // registration is in use, which will cause other - // threads to wait. - private final Map<ServiceRegistration<?>, Object> m_lockedRegsMap = new HashMap<ServiceRegistration<?>, Object>(); // Maps bundle to an array of usage counts. - private final Map<Bundle, UsageCount[]> m_inUseMap = new HashMap<Bundle, UsageCount[]>(); + private final ConcurrentMap<Bundle, UsageCount[]> m_inUseMap = new ConcurrentHashMap<Bundle, UsageCount[]>(); private final ServiceRegistryCallbacks m_callbacks; - private final WeakHashMap<ServiceReference<?>, ServiceReference<?>> m_blackList = - new WeakHashMap<ServiceReference<?>, ServiceReference<?>>(); - - private final static Class<?>[] m_hookClasses = { - org.osgi.framework.hooks.bundle.CollisionHook.class, - org.osgi.framework.hooks.bundle.FindHook.class, - org.osgi.framework.hooks.bundle.EventHook.class, - org.osgi.framework.hooks.service.EventHook.class, - org.osgi.framework.hooks.service.EventListenerHook.class, - org.osgi.framework.hooks.service.FindHook.class, - org.osgi.framework.hooks.service.ListenerHook.class, - org.osgi.framework.hooks.weaving.WeavingHook.class, - org.osgi.framework.hooks.weaving.WovenClassListener.class, - org.osgi.framework.hooks.resolver.ResolverHookFactory.class, - org.osgi.service.url.URLStreamHandlerService.class, - java.net.ContentHandler.class - }; - private final Map<Class<?>, Set<ServiceReference<?>>> m_allHooks = - new HashMap<Class<?>, Set<ServiceReference<?>>>(); + private final HookRegistry hookRegistry = new HookRegistry(); - public ServiceRegistry(Logger logger, ServiceRegistryCallbacks callbacks) + public ServiceRegistry(final Logger logger, final ServiceRegistryCallbacks callbacks) { m_logger = logger; m_callbacks = callbacks; - - List indices = new ArrayList(); - indices.add(Constants.OBJECTCLASS); - m_regCapSet = new CapabilitySet(indices, false); } - public ServiceReference<?>[] getRegisteredServices(Bundle bundle) + /** + * Get all service references for a bundle + * @param bundle + * @return List with all valid service references or {@code null}. + */ + public ServiceReference<?>[] getRegisteredServices(final Bundle bundle) { - ServiceRegistration<?>[] regs = m_regsMap.get(bundle); + final List<ServiceRegistration<?>> regs = m_regsMap.get(bundle); if (regs != null) { - List<Object> refs = new ArrayList<Object>(regs.length); - for (int i = 0; i < regs.length; i++) + final List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(regs.size()); + // this is a per bundle list, therefore synchronizing this should be fine + synchronized ( regs ) { - try + for (final ServiceRegistration<?> reg : regs) { - refs.add(regs[i].getReference()); - } - catch (IllegalStateException ex) - { - // Don't include the reference as it is not valid anymore + try + { + refs.add(reg.getReference()); + } + catch (final IllegalStateException ex) + { + // Don't include the reference as it is not valid anymore + } } } return refs.toArray(new ServiceReference[refs.size()]); @@ -113,50 +97,76 @@ public class ServiceRegistry return null; } - // Caller is expected to fire REGISTERED event. + /** + * Register a new service + * + * Caller must fire service event as this method is not doing it! + * + * @param bundle The bundle registering the service + * @param classNames The service class names + * @param svcObj The service object + * @param dict Optional service properties + * @return Service registration + */ public ServiceRegistration<?> registerService( - BundleContext context, String[] classNames, Object svcObj, Dictionary dict) - { - ServiceRegistrationImpl reg = null; - - synchronized (this) + final Bundle bundle, + final String[] classNames, + final Object svcObj, + final Dictionary dict) + { + // Create the service registration. + final ServiceRegistrationImpl reg = new ServiceRegistrationImpl( + this, bundle, classNames, m_currentServiceId.getAndIncrement(), svcObj, dict); + + // Keep track of registered hooks. + this.hookRegistry.addHooks(classNames, svcObj, reg.getReference()); + + // Get the bundles current registered services. + final List<ServiceRegistration<?>> newRegs = new ArrayList<ServiceRegistration<?>>(); + List<ServiceRegistration<?>> regs = m_regsMap.putIfAbsent(bundle, newRegs); + if (regs == null) { - Bundle bundle = context.getBundle(); - - // Create the service registration. - reg = new ServiceRegistrationImpl( - this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict); - - // Keep track of registered hooks. - addHooks(classNames, svcObj, reg.getReference()); - - // Get the bundles current registered services. - ServiceRegistration<?>[] regs = m_regsMap.get(bundle); - m_regsMap.put(bundle, addServiceRegistration(regs, reg)); - m_regCapSet.addCapability((BundleCapabilityImpl) reg.getReference()); + regs = newRegs; + } + // this is a per bundle list, therefore synchronizing this should be fine + synchronized ( regs ) + { + regs.add(reg); } + m_regCapSet.addCapability((BundleCapabilityImpl) reg.getReference()); return reg; } - public void unregisterService(Bundle bundle, ServiceRegistration<?> reg) + /** + * Unregister a service + * @param bundle The bundle unregistering the service + * @param reg The service registration + */ + public void unregisterService( + final Bundle bundle, + final ServiceRegistration<?> reg) { // If this is a hook, it should be removed. - removeHook(reg.getReference()); + this.hookRegistry.removeHooks(reg.getReference()); + + // Note that we don't lock the service registration here using + // the m_lockedRegsMap because we want to allow bundles to get + // the service during the unregistration process. However, since + // we do remove the registration from the service registry, no + // new bundles will be able to look up the service. - synchronized (this) + // Now remove the registered service. + final List<ServiceRegistration<?>> regs = m_regsMap.get(bundle); + if (regs != null) { - // Note that we don't lock the service registration here using - // the m_lockedRegsMap because we want to allow bundles to get - // the service during the unregistration process. However, since - // we do remove the registration from the service registry, no - // new bundles will be able to look up the service. - - // Now remove the registered service. - ServiceRegistration<?>[] regs = m_regsMap.get(bundle); - m_regsMap.put(bundle, removeServiceRegistration(regs, reg)); - m_regCapSet.removeCapability((BundleCapabilityImpl) reg.getReference()); + // this is a per bundle list, therefore synchronizing this should be fine + synchronized ( regs ) + { + regs.remove(reg); + } } + m_regCapSet.removeCapability((BundleCapabilityImpl) reg.getReference()); // Notify callback objects about unregistering service. if (m_callbacks != null) @@ -166,30 +176,28 @@ public class ServiceRegistry } // Now forcibly unget the service object for all stubborn clients. - ServiceReference<?> ref = reg.getReference(); - Bundle[] clients = getUsingBundles(ref); - for (int i = 0; (clients != null) && (i < clients.length); i++) - { - UsageCount[] usages = m_inUseMap.get(clients[i]); - for (int x = 0; (usages != null) && (x < usages.length); x++) - { - if (usages[x].m_ref.equals(ref)) - { - ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null)); - } - } - } + final ServiceReference<?> ref = reg.getReference(); + ungetServices(ref); + // Invalidate registration ((ServiceRegistrationImpl) reg).invalidate(); + // Bundles are allowed to get a reference while unregistering + // get fresh set of bundles (should be empty, but this is a sanity check) + ungetServices(ref); + } + + private void ungetServices(final ServiceReference<?> ref) + { + final Bundle[] clients = getUsingBundles(ref); for (int i = 0; (clients != null) && (i < clients.length); i++) { - UsageCount[] usages = m_inUseMap.get(clients[i]); + final UsageCount[] usages = m_inUseMap.get(clients[i]); for (int x = 0; (usages != null) && (x < usages.length); x++) { if (usages[x].m_ref.equals(ref)) { - ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null)); + ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null)); } } } @@ -201,15 +209,11 @@ public class ServiceRegistry * one. This method is only called be the framework to clean up after * a stopped bundle. * @param bundle the bundle whose services should be unregistered. - **/ - public void unregisterServices(Bundle bundle) + **/ + public void unregisterServices(final Bundle bundle) { // Simply remove all service registrations for the bundle. - ServiceRegistration<?>[] regs = null; - synchronized (this) - { - regs = m_regsMap.get(bundle); - } + final List<ServiceRegistration<?>> regs = m_regsMap.remove(bundle); // Note, there is no race condition here with respect to the // bundle registering more services, because its bundle context @@ -217,29 +221,33 @@ public class ServiceRegistry // be able to register more services. // Unregister each service. - for (int i = 0; (regs != null) && (i < regs.length); i++) + if (regs != null) { - if (((ServiceRegistrationImpl) regs[i]).isValid()) + final List<ServiceRegistration<?>> copyRefs; + // there shouldn't be a need to sync, but just to be safe + // we create a copy array and use that for iterating + synchronized ( regs ) { - try - { - regs[i].unregister(); - } - catch (IllegalStateException e) + copyRefs = new ArrayList<ServiceRegistration<?>>(regs); + } + for (final ServiceRegistration<?> reg : copyRefs) + { + if (((ServiceRegistrationImpl) reg).isValid()) { - // Ignore exception if the service has already been unregistered + try + { + reg.unregister(); + } + catch (final IllegalStateException e) + { + // Ignore exception if the service has already been unregistered + } } } } - - // Now remove the bundle itself. - synchronized (this) - { - m_regsMap.remove(bundle); - } } - public synchronized Collection getServiceReferences(String className, SimpleFilter filter) + public Collection<Capability> getServiceReferences(final String className, SimpleFilter filter) { if ((className == null) && (filter == null)) { @@ -254,7 +262,7 @@ public class ServiceRegistry else if ((className != null) && (filter != null)) { // Return services matching the class name and filter. - List<SimpleFilter> filters = new ArrayList<SimpleFilter>(2); + final List<SimpleFilter> filters = new ArrayList<SimpleFilter>(2); filters.add(new SimpleFilter(Constants.OBJECTCLASS, className, SimpleFilter.EQ)); filters.add(filter); filter = new SimpleFilter(null, filters, SimpleFilter.AND); @@ -264,12 +272,12 @@ public class ServiceRegistry return m_regCapSet.match(filter, false); } - public synchronized ServiceReference<?>[] getServicesInUse(Bundle bundle) + public ServiceReference<?>[] getServicesInUse(final Bundle bundle) { - UsageCount[] usages = m_inUseMap.get(bundle); + final UsageCount[] usages = m_inUseMap.get(bundle); if (usages != null) { - ServiceReference<?>[] refs = new ServiceReference[usages.length]; + final ServiceReference<?>[] refs = new ServiceReference[usages.length]; for (int i = 0; i < refs.length; i++) { refs[i] = usages[i].m_ref; @@ -291,57 +299,39 @@ public class ServiceRegistry final ServiceRegistrationImpl reg = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration(); - synchronized (this) + // We don't allow cycles when we call out to the service factory. + if ( reg.isLocked() ) { - // First make sure that no existing operation is currently - // being performed by another thread on the service registration. - for (Object o = m_lockedRegsMap.get(reg); (o != null); o = m_lockedRegsMap.get(reg)) + throw new ServiceException( + "ServiceFactory.getService() resulted in a cycle.", + ServiceException.FACTORY_ERROR, + null); + } + + // no concurrent operations on the same service registration + reg.lock(); + // Make sure the service registration is still valid. + if (reg.isValid()) + { + // Get the usage count, if any. + // if prototype, we always create a new usage + usage = isPrototype ? null : getUsageCount(bundle, ref, null); + + // If we don't have a usage count, then create one and + // since the spec says we increment usage count before + // actually getting the service object. + if (usage == null) { - // We don't allow cycles when we call out to the service factory. - if (o.equals(Thread.currentThread())) - { - throw new ServiceException( - "ServiceFactory.getService() resulted in a cycle.", - ServiceException.FACTORY_ERROR, - null); - } - - // Otherwise, wait for it to be freed. - try - { - wait(); - } - catch (InterruptedException ex) - { - } + usage = addUsageCount(bundle, ref, isPrototype); } - // Lock the service registration. - m_lockedRegsMap.put(reg, Thread.currentThread()); - - // Make sure the service registration is still valid. - if (reg.isValid()) + // Increment the usage count and grab the already retrieved + // service object, if one exists. + usage.m_count++; + svcObj = usage.m_svcObj; + if ( isServiceObjects ) { - // Get the usage count, if any. - // if prototype, we always create a new usage - usage = isPrototype ? null : getUsageCount(bundle, ref, null); - - // If we don't have a usage count, then create one and - // since the spec says we increment usage count before - // actually getting the service object. - if (usage == null) - { - usage = addUsageCount(bundle, ref, isPrototype); - } - - // Increment the usage count and grab the already retrieved - // service object, if one exists. - usage.m_count++; - svcObj = usage.m_svcObj; - if ( isServiceObjects ) - { - usage.m_serviceObjectsCount++; - } + usage.m_serviceObjectsCount++; } } @@ -362,81 +352,60 @@ public class ServiceRegistry // cache it in the usage count. If not, we should flush the usage // count. Either way, we need to unlock the service registration // so that any threads waiting for it can continue. - synchronized (this) + + // Before caching the service object, double check to see if + // the registration is still valid, since it may have been + // unregistered while we didn't hold the lock. + if (!reg.isValid() || (svcObj == null)) { - // Before caching the service object, double check to see if - // the registration is still valid, since it may have been - // unregistered while we didn't hold the lock. - if (!reg.isValid() || (svcObj == null)) - { - flushUsageCount(bundle, ref, usage); - } - else - { - usage.m_svcObj = svcObj; - } - m_lockedRegsMap.remove(reg); - notifyAll(); + flushUsageCount(bundle, ref, usage); + } + else + { + usage.m_svcObj = svcObj; } + reg.unlock(); } return (S) svcObj; } - public boolean ungetService(Bundle bundle, ServiceReference<?> ref, Object svcObj) + public boolean ungetService(final Bundle bundle, final ServiceReference<?> ref, final Object svcObj) { - // prototype scope is only possible if called from ServiceObjects - final boolean isPrototype = svcObj != null && ref.getProperty(Constants.SERVICE_SCOPE) == Constants.SCOPE_PROTOTYPE; - - UsageCount usage = null; - ServiceRegistrationImpl reg = + final ServiceRegistrationImpl reg = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration(); - synchronized (this) + if ( reg.isLocked() ) { - // First make sure that no existing operation is currently - // being performed by another thread on the service registration. - for (Object o = m_lockedRegsMap.get(reg); (o != null); o = m_lockedRegsMap.get(reg)) - { - // We don't allow cycles when we call out to the service factory. - if (o.equals(Thread.currentThread())) - { - throw new IllegalStateException( - "ServiceFactory.ungetService() resulted in a cycle."); - } + throw new IllegalStateException( + "ServiceFactory.ungetService() resulted in a cycle."); + } - // Otherwise, wait for it to be freed. - try - { - wait(); - } - catch (InterruptedException ex) - { - } - } + UsageCount usage = null; - // Get the usage count. - usage = getUsageCount(bundle, ref, svcObj); - // If there is no cached services, then just return immediately. - if (usage == null) + // First make sure that no existing operation is currently + // being performed by another thread on the service registration. + reg.lock(); + + // Get the usage count. + usage = getUsageCount(bundle, ref, svcObj); + // If there is no cached services, then just return immediately. + if (usage == null) + { + reg.unlock(); + return false; + } + // if this is a call from service objects and the service was not fetched from + // there, return false + if ( svcObj != null ) + { + // TODO have a proper conditional decrement and get, how??? + usage.m_serviceObjectsCount--; + if (usage.m_serviceObjectsCount < 0) { + reg.unlock(); return false; } - // if this is a call from service objects and the service was not fetched from - // there, return false - if ( svcObj != null ) - { - if ( usage.m_serviceObjectsCount > 0 ) - { - usage.m_serviceObjectsCount--; - } - else - { - return false; - } - } - // Lock the service registration. - m_lockedRegsMap.put(reg, Thread.currentThread()); } // If usage count will go to zero, then unget the service @@ -457,25 +426,22 @@ public class ServiceRegistry // the registration became invalid while we were not holding the // lock. Either way, unlock the service registration so that any // threads waiting for it can continue. - synchronized (this) - { - // Decrement usage count, which spec says should happen after - // ungetting the service object. - usage.m_count--; - - // If the registration is invalid or the usage count has reached - // zero, then flush it. - if (!reg.isValid() || (usage.m_count <= 0)) - { - usage.m_svcObj = null; - flushUsageCount(bundle, ref, usage); - } - // Release the registration lock so any waiting threads can - // continue. - m_lockedRegsMap.remove(reg); - notifyAll(); + // Decrement usage count, which spec says should happen after + // ungetting the service object. + usage.m_count--; + + // If the registration is invalid or the usage count has reached + // zero, then flush it. + if (!reg.isValid() || (usage.m_count <= 0)) + { + usage.m_svcObj = null; + flushUsageCount(bundle, ref, usage); } + + // Release the registration lock so any waiting threads can + // continue. + reg.unlock(); } return true; @@ -487,14 +453,9 @@ public class ServiceRegistry * used by the specified bundle. * @param bundle the bundle whose services are to be released. **/ - public void ungetServices(Bundle bundle) + public void ungetServices(final Bundle bundle) { - UsageCount[] usages; - synchronized (this) - { - usages = m_inUseMap.get(bundle); - } - + UsageCount[] usages = m_inUseMap.get(bundle); if (usages == null) { return; @@ -517,7 +478,7 @@ public class ServiceRegistry } } - public synchronized Bundle[] getUsingBundles(ServiceReference<?> ref) + public Bundle[] getUsingBundles(ServiceReference<?> ref) { Bundle[] bundles = null; for (Iterator<Map.Entry<Bundle, UsageCount[]>> iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); ) @@ -549,7 +510,7 @@ public class ServiceRegistry void servicePropertiesModified(ServiceRegistration<?> reg, Dictionary oldProps) { - updateHook(reg.getReference()); + this.hookRegistry.updateHooks(reg.getReference()); if (m_callbacks != null) { m_callbacks.serviceChanged( @@ -562,52 +523,6 @@ public class ServiceRegistry return m_logger; } - private static ServiceRegistration<?>[] addServiceRegistration( - ServiceRegistration<?>[] regs, ServiceRegistration<?> reg) - { - if (regs == null) - { - regs = new ServiceRegistration[] { reg }; - } - else - { - ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length + 1]; - System.arraycopy(regs, 0, newRegs, 0, regs.length); - newRegs[regs.length] = reg; - regs = newRegs; - } - return regs; - } - - private static ServiceRegistration<?>[] removeServiceRegistration( - ServiceRegistration<?>[] regs, ServiceRegistration<?> reg) - { - for (int i = 0; (regs != null) && (i < regs.length); i++) - { - if (regs[i].equals(reg)) - { - // If this is the only usage, then point to empty list. - if ((regs.length - 1) == 0) - { - regs = new ServiceRegistration[0]; - } - // Otherwise, we need to do some array copying. - else - { - ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length - 1]; - System.arraycopy(regs, 0, newRegs, 0, i); - if (i < newRegs.length) - { - System.arraycopy( - regs, i + 1, newRegs, i, newRegs.length - i); - } - regs = newRegs; - } - } - } - return regs; - } - /** * Utility method to retrieve the specified bundle's usage count for the * specified service reference. @@ -620,7 +535,7 @@ public class ServiceRegistry UsageCount[] usages = m_inUseMap.get(bundle); for (int i = 0; (usages != null) && (i < usages.length); i++) { - if (usages[i].m_ref.equals(ref) + if (usages[i].m_ref.equals(ref) && ((svcObj == null && !usages[i].m_prototype) || usages[i].m_svcObj == svcObj)) { return usages[i]; @@ -643,9 +558,7 @@ public class ServiceRegistry { UsageCount[] usages = m_inUseMap.get(bundle); - UsageCount usage = new UsageCount(); - usage.m_ref = ref; - usage.m_prototype = isPrototype; + UsageCount usage = new UsageCount(ref, isPrototype); if (usages == null) { @@ -714,152 +627,28 @@ public class ServiceRegistry } } - // - // Hook-related methods. - // - - boolean isHookBlackListed(ServiceReference<?> sr) - { - return m_blackList.containsKey(sr); - } - - void blackListHook(ServiceReference<?> sr) - { - m_blackList.put(sr, sr); - } - - static boolean isHook(String[] classNames, Class<?> hookClass, Object svcObj) - { - // For a service factory, we can only match names. - if (svcObj instanceof ServiceFactory) - { - for (String className : classNames) - { - if (className.equals(hookClass.getName())) - { - return true; - } - } - } - - // For a service object, check if its class matches. - if (hookClass.isAssignableFrom(svcObj.getClass())) - { - // But still only if it is registered under that interface. - String hookName = hookClass.getName(); - for (String className : classNames) - { - if (className.equals(hookName)) - { - return true; - } - } - } - return false; - } - - private void addHooks(String[] classNames, Object svcObj, ServiceReference<?> ref) + public HookRegistry getHookRegistry() { - for (Class<?> hookClass : m_hookClasses) - { - if (isHook(classNames, hookClass, svcObj)) - { - synchronized (m_allHooks) - { - Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass); - if (hooks == null) - { - hooks = new TreeSet<ServiceReference<?>>(Collections.reverseOrder()); - m_allHooks.put(hookClass, hooks); - } - hooks.add(ref); - } - } - } + return this.hookRegistry; } - private void updateHook(ServiceReference<?> ref) + private static class UsageCount { - // We maintain the hooks sorted, so if ranking has changed for example, - // we need to ensure the order remains correct by resorting the hooks. - Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref) - .getRegistration().getService(); - String [] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS); - - for (Class<?> hookClass : m_hookClasses) - { - if (isHook(classNames, hookClass, svcObj)) - { - synchronized (m_allHooks) - { - Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass); - if (hooks != null) - { - List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(hooks); - hooks.clear(); - hooks.addAll(refs); - } - } - } - } - } + public final ServiceReference<?> m_ref; + public final boolean m_prototype; - private void removeHook(ServiceReference<?> ref) - { - Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref) - .getRegistration().getService(); - String [] classNames = (String[]) ref.getProperty(Constants.OBJECTCLASS); + public volatile int m_count; + public volatile int m_serviceObjectsCount; - for (Class<?> hookClass : m_hookClasses) - { - if (isHook(classNames, hookClass, svcObj)) - { - synchronized (m_allHooks) - { - Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass); - if (hooks != null) - { - hooks.remove(ref); - if (hooks.isEmpty()) - { - m_allHooks.remove(hookClass); - } - } - } - } - } - } + public volatile Object m_svcObj; - public <S> Set<ServiceReference<S>> getHooks(Class<S> hookClass) - { - synchronized (m_allHooks) + UsageCount(final ServiceReference<?> ref, final boolean isPrototype) { - Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass); - if (hooks != null) - { - SortedSet<ServiceReference<?>> sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder()); - sorted.addAll(hooks); - return asTypedSortedSet(sorted); - } - return Collections.emptySet(); + m_ref = ref; + m_prototype = isPrototype; } } - private static <S> SortedSet<ServiceReference<S>> asTypedSortedSet( - SortedSet<ServiceReference<?>> ss) - { - return (SortedSet) ss; - } - - private static class UsageCount - { - public int m_count; - public ServiceReference<?> m_ref; - public Object m_svcObj; - public boolean m_prototype; - public int m_serviceObjectsCount; - } - public interface ServiceRegistryCallbacks { void serviceChanged(ServiceEvent event, Dictionary oldProps); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java Mon Apr 27 07:12:18 2015 @@ -57,8 +57,8 @@ import org.osgi.framework.wiring.BundleR import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.BundleWire; import org.osgi.framework.wiring.BundleWiring; -import org.osgi.resource.Requirement; import org.osgi.resource.Capability; +import org.osgi.resource.Requirement; import org.osgi.resource.Resource; import org.osgi.resource.Wire; import org.osgi.resource.Wiring; @@ -121,7 +121,7 @@ class StatefulResolver void start() { - m_registry.registerService(m_felix._getBundleContext(), + m_registry.registerService(m_felix, new String[] { Resolver.class.getName() }, m_resolver, null); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java Mon Apr 27 07:12:18 2015 @@ -24,6 +24,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -31,7 +32,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.TreeMap; +import java.util.SortedMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; import org.apache.felix.framework.util.SecureAction; import org.apache.felix.framework.util.StringComparator; @@ -43,8 +46,8 @@ import org.osgi.resource.Capability; public class CapabilitySet { - private final Map<String, Map<Object, Set<BundleCapability>>> m_indices; - private final Set<Capability> m_capSet = new HashSet<Capability>(); + private final SortedMap<String, Map<Object, Set<BundleCapability>>> m_indices; // Should also be concurrent! + private final Set<Capability> m_capSet = Collections.newSetFromMap(new ConcurrentHashMap<Capability, Boolean>()); private final static SecureAction m_secureAction = new SecureAction(); public void dump() @@ -76,11 +79,11 @@ public class CapabilitySet } } - public CapabilitySet(List<String> indexProps, boolean caseSensitive) + public CapabilitySet(final List<String> indexProps, final boolean caseSensitive) { m_indices = (caseSensitive) - ? new TreeMap<String, Map<Object, Set<BundleCapability>>>() - : new TreeMap<String, Map<Object, Set<BundleCapability>>>( + ? new ConcurrentSkipListMap<String, Map<Object, Set<BundleCapability>>>() + : new ConcurrentSkipListMap<String, Map<Object, Set<BundleCapability>>>( StringComparator.COMPARATOR); for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++) { @@ -89,7 +92,7 @@ public class CapabilitySet } } - public void addCapability(BundleCapability cap) + public void addCapability(final BundleCapability cap) { m_capSet.add(cap); @@ -134,7 +137,7 @@ public class CapabilitySet caps.add(cap); } - public void removeCapability(BundleCapability cap) + public void removeCapability(final BundleCapability cap) { if (m_capSet.remove(cap)) { @@ -181,15 +184,15 @@ public class CapabilitySet } } - public Set<Capability> match(SimpleFilter sf, boolean obeyMandatory) + public Set<Capability> match(final SimpleFilter sf, final boolean obeyMandatory) { - Set<Capability> matches = match(m_capSet, sf); + final Set<Capability> matches = match(m_capSet, sf); return (obeyMandatory) ? matchMandatory(matches, sf) : matches; } - private Set<Capability> match(Set<Capability> caps, SimpleFilter sf) + private Set<Capability> match(Set<Capability> caps, final SimpleFilter sf) { Set<Capability> matches = new HashSet<Capability>(); @@ -203,7 +206,7 @@ public class CapabilitySet // For AND we calculate the intersection of each subfilter. // We can short-circuit the AND operation if there are no // remaining capabilities. - List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue(); + final List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue(); for (int i = 0; (caps.size() > 0) && (i < sfs.size()); i++) { matches = match(caps, sfs.get(i)); @@ -405,13 +408,13 @@ public class CapabilitySet { //Do nothing will check later if rhs is null } - + if(rhs != null && rhs instanceof VersionRange) { return ((VersionRange)rhs).isInRange((Version)lhs); } } - + // If the type is comparable, then we can just return the // result immediately. if (lhs instanceof Comparable) Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java Mon Apr 27 07:12:18 2015 @@ -551,7 +551,7 @@ public class EventDispatcher ServiceEvent event, Framework felix, Map<BundleContext, List<ListenerInfo>> listeners) { Set<ServiceReference<org.osgi.framework.hooks.service.EventHook>> ehs = - m_registry.getHooks(org.osgi.framework.hooks.service.EventHook.class); + m_registry.getHookRegistry().getHooks(org.osgi.framework.hooks.service.EventHook.class); if ((ehs != null) && !ehs.isEmpty()) { // Create a whitelist of bundle context for bundle listeners, @@ -574,7 +574,7 @@ public class EventDispatcher } Set<ServiceReference<org.osgi.framework.hooks.service.EventListenerHook>> elhs = - m_registry.getHooks(org.osgi.framework.hooks.service.EventListenerHook.class); + m_registry.getHookRegistry().getHooks(org.osgi.framework.hooks.service.EventListenerHook.class); if ((elhs != null) && !elhs.isEmpty()) { List<ListenerInfo> systemBundleListeners = null; @@ -676,7 +676,7 @@ public class EventDispatcher { // Create a whitelist of bundle context, if we have hooks. Set<BundleContext> whitelist = null; - Set<ServiceReference<T>> hooks = m_registry.getHooks(hookClass); + Set<ServiceReference<T>> hooks = m_registry.getHookRegistry().getHooks(hookClass); if ((hooks != null) && !hooks.isEmpty()) { boolean systemBundleListener = false; Modified: felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java (original) +++ felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java Mon Apr 27 07:12:18 2015 @@ -55,21 +55,21 @@ public class ServiceRegistryTest extends } }; - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {EventHook.class.getName()}, hook, new Hashtable()); - assertEquals(1, sr.getHooks(EventHook.class).size()); - assertTrue(sr.getHooks(EventHook.class).iterator().next() instanceof ServiceReference); - assertSame(reg.getReference(), sr.getHooks(EventHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {EventHook.class.getName()}, hook, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertTrue(sr.getHookRegistry().getHooks(EventHook.class).iterator().next() instanceof ServiceReference); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterEventHookServiceFactory() @@ -88,20 +88,20 @@ public class ServiceRegistryTest extends sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {EventHook.class.getName()}, sf, new Hashtable()); - assertEquals(1, sr.getHooks(EventHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(EventHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {EventHook.class.getName()}, sf, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterFindHookService() @@ -124,20 +124,20 @@ public class ServiceRegistryTest extends } }; - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {FindHook.class.getName()}, hook, new Hashtable()); - assertEquals(1, sr.getHooks(FindHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(FindHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {FindHook.class.getName()}, hook, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterFindHookServiceFactory() @@ -156,20 +156,20 @@ public class ServiceRegistryTest extends sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {FindHook.class.getName()}, sf, new Hashtable()); - assertEquals(1, sr.getHooks(FindHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(FindHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {FindHook.class.getName()}, sf, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterListenerHookService() @@ -195,20 +195,20 @@ public class ServiceRegistryTest extends } }; - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {ListenerHook.class.getName()}, hook, new Hashtable()); - assertEquals(1, sr.getHooks(ListenerHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(ListenerHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {ListenerHook.class.getName()}, hook, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterListenerHookServiceFactory() @@ -227,20 +227,20 @@ public class ServiceRegistryTest extends sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {ListenerHook.class.getName()}, sf, new Hashtable()); - assertEquals(1, sr.getHooks(ListenerHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(ListenerHook.class).iterator().next()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {ListenerHook.class.getName()}, sf, new Hashtable()); + assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); - assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterCombinedService() @@ -281,28 +281,28 @@ public class ServiceRegistryTest extends } CombinedService hook = new CombinedService(); - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] { + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] { Runnable.class.getName(), ListenerHook.class.getName(), FindHook.class.getName(), EventHook.class.getName()}, hook, new Hashtable()); - assertEquals(1, sr.getHooks(ListenerHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(ListenerHook.class).iterator().next()); + assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); - assertEquals(1, sr.getHooks(EventHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(EventHook.class).iterator().next()); + assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); - assertEquals(1, sr.getHooks(FindHook.class).size()); - assertSame(reg.getReference(), sr.getHooks(FindHook.class).iterator().next()); + assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); sr.unregisterService(b, reg); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Should be no hooks left after unregistration", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterPlainService() @@ -318,17 +318,17 @@ public class ServiceRegistryTest extends ServiceRegistry sr = new ServiceRegistry(new Logger(), null); String svcObj = "hello"; - assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size()); - ServiceRegistration reg = sr.registerService(c, new String [] {String.class.getName()}, svcObj, new Hashtable()); - assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); + ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {String.class.getName()}, svcObj, new Hashtable()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); - assertEquals("Unregistration should have no effect", 0, sr.getHooks(EventHook.class).size()); - assertEquals("Unregistration should have no effect", 0, sr.getHooks(FindHook.class).size()); - assertEquals("Unregistration should have no effect", 0, sr.getHooks(ListenerHook.class).size()); + assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); + assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); + assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } } Modified: felix/trunk/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java?rev=1676200&r1=1676199&r2=1676200&view=diff ============================================================================== --- felix/trunk/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java (original) +++ felix/trunk/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java Mon Apr 27 07:12:18 2015 @@ -80,8 +80,8 @@ public class EventDispatcherTest extends Logger logger = new Logger(); ServiceRegistry registry = new ServiceRegistry(logger, null); - registry.registerService(b4.getBundleContext(), new String [] {EventHook.class.getName()}, eh1, new Hashtable()); - registry.registerService(b4.getBundleContext(), new String [] {EventHook.class.getName()}, eh2, new Hashtable()); + registry.registerService(b4, new String [] {EventHook.class.getName()}, eh1, new Hashtable()); + registry.registerService(b4, new String [] {EventHook.class.getName()}, eh2, new Hashtable()); // -- Set up event dispatcher EventDispatcher ed = new EventDispatcher(logger, registry);