Added synchronization blocks to ServiceTracker and AspectFilterIndex to solve and prevent concurrency issues.
Fixed issue in AdapterServiceImpl which did not handle aspect services correctly.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1303396 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
index b9b39b2..260ef79 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
@@ -87,15 +87,24 @@
ServiceReference ref = (ServiceReference) properties[0];
Properties props = new Properties();
String[] keys = ref.getPropertyKeys();
+ String serviceIdToTrack = null;
for (int i = 0; i < keys.length; i++) {
String key = keys[i];
- if (key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(DependencyManager.ASPECT) || key.equals(Constants.OBJECTCLASS)) {
- // do not copy these
+ if (key.equals(DependencyManager.ASPECT)) {
+ // if we're handed an aspect fetch the aspect property as the service id to track, but do not copy it
+ serviceIdToTrack = ref.getProperty(key).toString();
+ }
+ if (key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(Constants.OBJECTCLASS)) {
+ // do not copy these either
}
else {
props.put(key, ref.getProperty(key));
}
}
+ if (serviceIdToTrack == null) {
+ // we're not handed an aspect so we can use the service id to track
+ serviceIdToTrack = ref.getProperty(Constants.SERVICE_ID).toString();
+ }
if (m_serviceProperties != null) {
Enumeration e = m_serviceProperties.keys();
while (e.hasMoreElements()) {
@@ -107,8 +116,8 @@
dependencies.remove(0);
ServiceDependency dependency = m_manager.createServiceDependency()
// create a dependency on both the service id we're adapting and possible aspects for this given service id
- .setService(m_adapteeInterface, "(|(" + Constants.SERVICE_ID + "=" + ref.getProperty(Constants.SERVICE_ID)
- + ")(" + DependencyManager.ASPECT + "=" + ref.getProperty(Constants.SERVICE_ID) + "))")
+ .setService(m_adapteeInterface, "(|(" + Constants.SERVICE_ID + "=" + serviceIdToTrack
+ + ")(" + DependencyManager.ASPECT + "=" + serviceIdToTrack + "))")
.setRequired(true);
if (m_autoConfig != null) {
dependency.setAutoConfig(m_autoConfig);
@@ -116,7 +125,7 @@
if (m_add != null || m_change != null || m_remove != null || m_swap != null) {
dependency.setCallbacks(m_add, m_change, m_remove, m_swap);
}
-
+
Component service = m_manager.createComponent()
.setInterface(m_serviceInterfaces, props)
.setImplementation(m_serviceImpl)
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AspectFilterIndex.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AspectFilterIndex.java
index 4bef15e..c16dada 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AspectFilterIndex.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AspectFilterIndex.java
@@ -129,7 +129,10 @@
List /* <ServiceReference> */ result = new ArrayList();
FilterData data = getFilterData(clazz, filter);
if (data != null) {
- SortedSet /* <ServiceReference> */ list = (SortedSet) m_sidToServiceReferencesMap.get(Long.valueOf(data.serviceId));
+ SortedSet /* <ServiceReference> */ list = null;
+ synchronized (m_sidToServiceReferencesMap) {
+ list = (SortedSet) m_sidToServiceReferencesMap.get(Long.valueOf(data.serviceId));
+ }
if (list != null) {
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/tracker/ServiceTracker.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/tracker/ServiceTracker.java
index 21504a1..c7440fc 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/tracker/ServiceTracker.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/tracker/ServiceTracker.java
@@ -928,64 +928,78 @@
private ServiceReference highestTrackedCache(long serviceId) {
Long sid = Long.valueOf(serviceId);
- TreeSet services = (TreeSet) m_highestTrackedCache.get(sid);
- if (services != null && services.size() > 0) {
- ServiceReference result = (ServiceReference) services.last();
- return result;
- }
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestTrackedCache.get(sid);
+ if (services != null && services.size() > 0) {
+ ServiceReference result = (ServiceReference) services.last();
+ return result;
+ }
+ }
return null;
}
private void addHighestTrackedCache(ServiceReference reference) {
Long serviceId = ServiceUtil.getServiceIdObject(reference);
- TreeSet services = (TreeSet) m_highestTrackedCache.get(serviceId);
- if (services == null) {
- services = new TreeSet();
- m_highestTrackedCache.put(serviceId, services);
- }
- services.add(reference);
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestTrackedCache.get(serviceId);
+ if (services == null) {
+ services = new TreeSet();
+ m_highestTrackedCache.put(serviceId, services);
+ }
+ services.add(reference);
+ }
}
private void removeHighestTrackedCache(ServiceReference reference) {
Long serviceId = ServiceUtil.getServiceIdObject(reference);
- TreeSet services = (TreeSet) m_highestTrackedCache.get(serviceId);
- if (services != null) {
- services.remove(reference);
- }
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestTrackedCache.get(serviceId);
+ if (services != null) {
+ services.remove(reference);
+ }
+ }
}
private void clearHighestTrackedCache() {
- m_highestTrackedCache.clear();
+ synchronized (this) {
+ m_highestTrackedCache.clear();
+ }
}
private final HashMap m_highestHiddenCache = new HashMap();
private ServiceReference highestHiddenCache(long serviceId) {
Long sid = Long.valueOf(serviceId);
- TreeSet services = (TreeSet) m_highestHiddenCache.get(sid);
- if (services != null && services.size() > 0) {
- ServiceReference result = (ServiceReference) services.last();
- return result;
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestHiddenCache.get(sid);
+ if (services != null && services.size() > 0) {
+ ServiceReference result = (ServiceReference) services.last();
+ return result;
+ }
}
return null;
}
private void addHighestHiddenCache(ServiceReference reference) {
Long serviceId = ServiceUtil.getServiceIdObject(reference);
- TreeSet services = (TreeSet) m_highestHiddenCache.get(serviceId);
- if (services == null) {
- services = new TreeSet();
- m_highestHiddenCache.put(serviceId, services);
- }
- services.add(reference);
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestHiddenCache.get(serviceId);
+ if (services == null) {
+ services = new TreeSet();
+ m_highestHiddenCache.put(serviceId, services);
+ }
+ services.add(reference);
+ }
}
private void removeHighestHiddenCache(ServiceReference reference) {
Long serviceId = ServiceUtil.getServiceIdObject(reference);
- TreeSet services = (TreeSet) m_highestHiddenCache.get(serviceId);
- if (services != null) {
- services.remove(reference);
- }
+ synchronized (this) {
+ TreeSet services = (TreeSet) m_highestHiddenCache.get(serviceId);
+ if (services != null) {
+ services.remove(reference);
+ }
+ }
}
/**