FELIX-3564: Fixed memory leak in ServiceRegistryCache

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1351732 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
index 62116f7..df648e9 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/FilterIndex.java
@@ -42,6 +42,6 @@
     public void serviceChanged(ServiceEvent event);
     /** Adds a service listener to this filter index. */
     public void addServiceListener(ServiceListener listener, String filter);
-    /** Removes a service listener from this filter index. */
+    /** Removes a service listener from this filter index. If the listener is not present in the filter index, this method does nothing. */
     public void removeServiceListener(ServiceListener listener);
 }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AdapterFilterIndex.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AdapterFilterIndex.java
index 4d466e2..2543746 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AdapterFilterIndex.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AdapterFilterIndex.java
@@ -172,12 +172,15 @@
     public void removeServiceListener(ServiceListener listener) {
         synchronized (m_sidToListenersMap) {
             String filter = (String) m_listenerToFilterMap.remove(listener);
-            FilterData data = getFilterData(null, filter);
-            if (data != null) {
-            	Long sidObject = Long.valueOf(data.serviceId);
-            	List /* ServiceListener */ listeners = (List) m_sidToListenersMap.get(sidObject);
-            	if (listeners != null) {
-            		listeners.remove(listener);
+            if (filter != null) {
+            	// the listener does exist
+            	FilterData data = getFilterData(null, filter);
+            	if (data != null) {
+            		Long sidObject = Long.valueOf(data.serviceId);
+            		List /* ServiceListener */ listeners = (List) m_sidToListenersMap.get(sidObject);
+            		if (listeners != null) {
+            			listeners.remove(listener);
+            		}
             	}
             }
         }
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 70bf333..4e79eb4 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
@@ -189,14 +189,17 @@
     public void removeServiceListener(ServiceListener listener) {
         synchronized (m_sidToRankingToListenersMap) {
             String filter = (String) m_listenerToFilterMap.remove(listener);
-            FilterData data = getFilterData(null, filter);
-            if (data != null) {
-                synchronized (m_sidToRankingToListenersMap) {
-                    SortedMap /* <Integer, ServiceListener> */ rankingToListenersMap = (SortedMap) m_sidToRankingToListenersMap.get(Long.valueOf(data.serviceId));
-                    if (rankingToListenersMap != null) {
-                        rankingToListenersMap.remove(Integer.valueOf(data.ranking));
-                    }
-                }
+            if (filter != null) {
+            	// the listener does exist
+	            FilterData data = getFilterData(null, filter);
+	            if (data != null) {
+	                synchronized (m_sidToRankingToListenersMap) {
+	                    SortedMap /* <Integer, ServiceListener> */ rankingToListenersMap = (SortedMap) m_sidToRankingToListenersMap.get(Long.valueOf(data.serviceId));
+	                    if (rankingToListenersMap != null) {
+	                        rankingToListenersMap.remove(Integer.valueOf(data.ranking));
+	                    }
+	                }
+	            }
             }
         }
     }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/BundleContextInterceptor.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/BundleContextInterceptor.java
index 51cc43d..e39de62 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/BundleContextInterceptor.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/BundleContextInterceptor.java
@@ -64,13 +64,13 @@
     }
 
     public void removeServiceListener(ServiceListener listener) {
-        FilterIndex filterIndex = m_cache.hasFilterIndexFor(null, null);
-        if (filterIndex != null) {
-            filterIndex.removeServiceListener(listener);
-        }
-        else {
-            m_context.removeServiceListener(listener);
-        }
+    	// remove servicelistener. although it would be prettier to find the correct filterindex first it's
+    	// probaby faster to do a brute force removal.
+    	Iterator filterIndexIterator = m_cache.getFilterIndices().iterator();
+    	while (filterIndexIterator.hasNext()) {
+    		((FilterIndex) filterIndexIterator.next()).removeServiceListener(listener);
+    	}
+    	m_context.removeServiceListener(listener);
     }
 
     public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/MultiPropertyExactFilter.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/MultiPropertyExactFilter.java
index fb4f313..f0b7705 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/MultiPropertyExactFilter.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/MultiPropertyExactFilter.java
@@ -398,19 +398,22 @@
     public void removeServiceListener(ServiceListener listener) {
         synchronized (m_keyToListenersMap) {
             String filter = (String) m_listenerToFilterMap.remove(listener);
-            List keys = createKeysFromFilter(null, filter);
-            Iterator iterator = keys.iterator();
-            while (iterator.hasNext()) {
-                String key = (String) iterator.next();
-                
-                boolean result = filter != null;
-                if (result) {
-                    List /* <ServiceListener> */ listeners = (List) m_keyToListenersMap.get(key);
-                    if (listeners != null) {
-                        listeners.remove(listener);
-                    }
-                    // TODO actually, if listeners == null that would be strange....
-                }
+            if (filter != null) {
+            	// the listener does exist
+            	List keys = createKeysFromFilter(null, filter);
+            	Iterator iterator = keys.iterator();
+            	while (iterator.hasNext()) {
+            		String key = (String) iterator.next();
+            		
+            		boolean result = filter != null;
+            		if (result) {
+            			List /* <ServiceListener> */ listeners = (List) m_keyToListenersMap.get(key);
+            			if (listeners != null) {
+            				listeners.remove(listener);
+            			}
+            			// TODO actually, if listeners == null that would be strange....
+            		}
+            	}
             }
         }
     }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/ServiceRegistryCache.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/ServiceRegistryCache.java
index 3e2bcd2..41f7fd6 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/ServiceRegistryCache.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/ServiceRegistryCache.java
@@ -169,4 +169,8 @@
         sb.append("]");
         return sb.toString();
     }
+
+	public List getFilterIndices() {
+		return m_filterIndexList;
+	}
 }