FELIX-4866 : Improve service registry
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1676200 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 3511b6f..08e4ed7 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3330,7 +3330,7 @@
// 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 @@
{
// 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 @@
}
}
- 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 @@
}
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 @@
// 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 @@
// 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);
}
//
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
index 995faad..db4a611 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
@@ -54,7 +54,7 @@
@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);
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
index a0173ed..7bc42ce 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -52,7 +52,7 @@
@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);
diff --git a/framework/src/main/java/org/apache/felix/framework/HookRegistry.java b/framework/src/main/java/org/apache/felix/framework/HookRegistry.java
new file mode 100644
index 0000000..0814948
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/HookRegistry.java
@@ -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);
+ }
+
+}
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index 6d77019..ed22354 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -66,6 +66,10 @@
// 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 @@
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
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index a975085..9fdad0d 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -22,90 +22,74 @@
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;
- // Maps bundle to an array of service registrations.
- private final Map<Bundle, ServiceRegistration<?>[]> m_regsMap = Collections.synchronizedMap(new HashMap<Bundle, ServiceRegistration<?>[]>());
- // Capability set for all service registrations.
- private final CapabilitySet m_regCapSet;
- // 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>();
+ /** Counter for the service id */
+ private final AtomicLong m_currentServiceId = new AtomicLong(1);
+
+ // Maps bundle to an array of service registrations.
+ private final ConcurrentMap<Bundle, List<ServiceRegistration<?>>> m_regsMap = new ConcurrentHashMap<Bundle, List<ServiceRegistration<?>>>();
+
+ // Capability set for all service registrations.
+ private final CapabilitySet m_regCapSet = new CapabilitySet(Collections.singletonList(Constants.OBJECTCLASS), false);
+
// 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 HookRegistry hookRegistry = new HookRegistry();
- 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<?>>>();
-
- 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 @@
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)
+ final Bundle bundle,
+ final String[] classNames,
+ final Object svcObj,
+ final Dictionary dict)
{
- ServiceRegistrationImpl reg = null;
+ // Create the service registration.
+ final ServiceRegistrationImpl reg = new ServiceRegistrationImpl(
+ this, bundle, classNames, m_currentServiceId.getAndIncrement(), svcObj, dict);
- synchronized (this)
+ // 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());
- synchronized (this)
+ // 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.
+ 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 @@
}
// 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 @@
* 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 @@
// 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
+ copyRefs = new ArrayList<ServiceRegistration<?>>(regs);
+ }
+ for (final ServiceRegistration<?> reg : copyRefs)
+ {
+ if (((ServiceRegistrationImpl) reg).isValid())
{
- regs[i].unregister();
- }
- catch (IllegalStateException e)
- {
- // 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 @@
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 @@
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 @@
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))
- {
- // 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);
- }
+ 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)
- {
- }
+ // 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)
+ {
+ 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 @@
// 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 @@
// 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))
{
- // 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();
+ 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 @@
* 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 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 @@
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 @@
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 @@
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 @@
{
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,150 +627,26 @@
}
}
- //
- // Hook-related methods.
- //
-
- boolean isHookBlackListed(ServiceReference<?> sr)
+ public HookRegistry getHookRegistry()
{
- 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)
- {
- 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);
- }
- }
- }
- }
-
- private void updateHook(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.
- 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);
- }
- }
- }
- }
- }
-
- private void removeHook(ServiceReference<?> ref)
- {
- 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)
- {
- hooks.remove(ref);
- if (hooks.isEmpty())
- {
- m_allHooks.remove(hookClass);
- }
- }
- }
- }
- }
- }
-
- public <S> Set<ServiceReference<S>> getHooks(Class<S> hookClass)
- {
- synchronized (m_allHooks)
- {
- 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();
- }
- }
-
- private static <S> SortedSet<ServiceReference<S>> asTypedSortedSet(
- SortedSet<ServiceReference<?>> ss)
- {
- return (SortedSet) ss;
+ return this.hookRegistry;
}
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 final ServiceReference<?> m_ref;
+ public final boolean m_prototype;
+
+ public volatile int m_count;
+ public volatile int m_serviceObjectsCount;
+
+ public volatile Object m_svcObj;
+
+ UsageCount(final ServiceReference<?> ref, final boolean isPrototype)
+ {
+ m_ref = ref;
+ m_prototype = isPrototype;
+ }
}
public interface ServiceRegistryCallbacks
diff --git a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
index 3ec6c76..de37097 100644
--- a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
@@ -57,8 +57,8 @@
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 @@
void start()
{
- m_registry.registerService(m_felix._getBundleContext(),
+ m_registry.registerService(m_felix,
new String[] { Resolver.class.getName() },
m_resolver,
null);
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
index 2e29b53..629d34d 100644
--- a/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
@@ -24,6 +24,7 @@
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.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 @@
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 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 void addCapability(BundleCapability cap)
+ public void addCapability(final BundleCapability cap)
{
m_capSet.add(cap);
@@ -134,7 +137,7 @@
caps.add(cap);
}
- public void removeCapability(BundleCapability cap)
+ public void removeCapability(final BundleCapability cap)
{
if (m_capSet.remove(cap))
{
@@ -181,15 +184,15 @@
}
}
- 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 @@
// 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 @@
{
//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)
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index 0435464..48208bf 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -551,7 +551,7 @@
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 @@
}
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 @@
{
// 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;
diff --git a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
index 6f3b92f..3db085a 100644
--- a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
@@ -55,21 +55,21 @@
}
};
- 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 @@
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 @@
}
};
- 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 @@
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 @@
}
};
- 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 @@
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 @@
}
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 @@
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());
}
}
diff --git a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
index a6eda11..13f5a63 100644
--- a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
@@ -80,8 +80,8 @@
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);