cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@apache.org
Subject svn commit: r895985 - in /cxf/dosgi/trunk/discovery/local/src: main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java
Date Tue, 05 Jan 2010 11:02:07 GMT
Author: davidb
Date: Tue Jan  5 11:02:04 2010
New Revision: 895985

URL: http://svn.apache.org/viewvc?rev=895985&view=rev
Log:
Added remove functionality for local discovery.
Additional tests for local discovery.

Modified:
    cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java

Modified: cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java?rev=895985&r1=895984&r2=895985&view=diff
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java
(original)
+++ cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscovery.java
Tue Jan  5 11:02:04 2010
@@ -19,13 +19,14 @@
 package org.apache.cxf.dosgi.discovery.local;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Logger;
 
@@ -61,39 +62,26 @@
 
             @Override
             public Object addingService(ServiceReference reference) {
-                System.out.println("@@@@ " + reference);
-                for (String key : reference.getPropertyKeys()) {
-                    Object val = reference.getProperty(key);
-                    if (val.getClass().isArray()) {
-                        val = Arrays.asList((Object []) val);
-                    }
-                    System.out.println("-----" + key + ":" + val);
-                }
                 Object svc = super.addingService(reference);
-                cacheTracker(reference, svc);
+                registerTracker(reference, svc);
                 return svc;
             }
 
             @Override
-            public void modifiedService(ServiceReference reference,
-                    Object service) {
-                System.out.println("#### " + reference);
-                for (String key : reference.getPropertyKeys()) {
-                    Object val = reference.getProperty(key);
-                    if (val.getClass().isArray()) {
-                        val = Arrays.asList((Object []) val);
-                    }
-                    System.out.println("-----" + key + ":" + val);
-                }
-
-                cacheTracker(reference, service);
+            public void modifiedService(ServiceReference reference, Object service) {
+                super.modifiedService(reference, service);
+                clearTracker(service);
+                
+                // This may cause duplicate registrations of remote services,
+                // but that's fine and should be filtered out on another level.
+                // See Remove Service Admin spec section 122.6.3
+                registerTracker(reference, service);
             }
 
             @Override
-            public void removedService(ServiceReference reference,
-                    Object service) {
-                // TODO Auto-generated method stub
+            public void removedService(ServiceReference reference, Object service) {
                 super.removedService(reference, service);
+                clearTracker(service);
             }
             
         };
@@ -116,7 +104,7 @@
         }
     }
 
-    protected void cacheTracker(ServiceReference reference, Object svc) {
+    void registerTracker(ServiceReference reference, Object svc) {
         if (svc instanceof EndpointListener) {
             EndpointListener listener = (EndpointListener) svc;
             Collection<String> filters = addListener(reference, listener);
@@ -124,6 +112,16 @@
         }
     }
 
+    void clearTracker(Object svc) {
+        if (svc instanceof EndpointListener) {
+            EndpointListener listener = (EndpointListener) svc;
+            removeListener(listener);
+            // If the tracker was removed or the scope was changed this doesn't require 
+            // additional callbacks on the tracker. Its the responsibility of the tracker
+            // itself to clean up any orphans. See Remote Service Admin spec 122.6.3
+        }
+    }
+
     private Collection<String> addListener(ServiceReference reference,
             EndpointListener listener) {
         List<String> filters = 
@@ -145,6 +143,21 @@
         
         return filters;
     }
+    
+    private void removeListener(EndpointListener listener) {
+        Collection<String> filters = listenerToFilters.remove(listener);
+        if (filters == null) {
+            return;
+        }
+        
+        for (String filter : filters) {
+            Collection<EndpointListener> listeners = filterToListeners.get(filter);
+            if (listeners == null) {
+                continue;
+            }
+            listeners.remove(listener);
+        }        
+    }
 
     public void shutDown() {
         bundleContext.removeBundleListener(this);
@@ -158,7 +171,7 @@
             findDeclaredRemoteServices(be.getBundle());
             break;
         case BundleEvent.STOPPING:
-            // TODO
+            removeServicesDeclaredInBundle(be.getBundle());
             break;
         }
     }
@@ -171,10 +184,24 @@
         }
     }
 
+    private void removeServicesDeclaredInBundle(Bundle bundle) {
+        for (Iterator<Entry<EndpointDescription, Bundle>> i = endpointDescriptions.entrySet().iterator();
i.hasNext(); ) {
+            Entry<EndpointDescription, Bundle> entry = i.next();
+            if (bundle.equals(entry.getValue())) {
+                removedEndpointDescription(entry.getKey());
+                i.remove();
+            }
+        }
+    }
+
     private void addedEndpointDescription(EndpointDescription ed) {
         triggerCallbacks(ed, true);
     }
 
+    private void removedEndpointDescription(EndpointDescription ed) {
+        triggerCallbacks(ed, false);
+    }
+
     private void triggerCallbacks(EndpointDescription ed, boolean added) {
         for (Map.Entry<EndpointListener, Collection<String>> entry : listenerToFilters.entrySet())
{
             for (String match : entry.getValue()) {

Modified: cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java?rev=895985&r1=895984&r2=895985&view=diff
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java
(original)
+++ cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryTest.java
Tue Jan  5 11:02:04 2010
@@ -21,10 +21,12 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -145,17 +147,50 @@
         ld.bundleChanged(be0);
         assertEquals(0, ld.endpointDescriptions.size());
         
+        // Create an EndpointListener
+        final Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, "(objectClass=*)");
+        ServiceReference sr = EasyMock.createMock(ServiceReference.class);
+        EasyMock.expect(sr.getPropertyKeys()).andReturn(props.keySet().toArray(new String
[] {})).anyTimes();
+        EasyMock.expect(sr.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>()
{
+            public Object answer() throws Throwable {
+                return props.get(EasyMock.getCurrentArguments()[0]);
+            }
+        }).anyTimes();                
+        EasyMock.replay(sr);
+
+        EndpointListener el = EasyMock.createMock(EndpointListener.class);
+        el.endpointAdded((EndpointDescription) EasyMock.anyObject(), EasyMock.eq("(objectClass=*)"));
+        EasyMock.expectLastCall();
+        EasyMock.replay(el);
+        ld.registerTracker(sr, el);
+        
+        // Start the bundle
         BundleEvent be = new BundleEvent(BundleEvent.STARTED, bundle);
         ld.bundleChanged(be);
         assertEquals(1, ld.endpointDescriptions.size());
         EndpointDescription ed = ld.endpointDescriptions.keySet().iterator().next();
         assertEquals("http://somewhere:12345", ed.getRemoteURI());
         assertSame(bundle, ld.endpointDescriptions.get(ed));
+        
+        EasyMock.verify(el);
+
+        // Stop the bundle
+        EasyMock.reset(el);
+        el.endpointRemoved((EndpointDescription) EasyMock.anyObject(), EasyMock.eq("(objectClass=*)"));
+        EasyMock.expectLastCall();
+        EasyMock.replay(el);
+        
+        BundleEvent be1 = new BundleEvent(BundleEvent.STOPPING, bundle);
+        ld.bundleChanged(be1);
+        assertEquals(0, ld.endpointDescriptions.size());
+        
+        EasyMock.verify(el);
     }
     
-    public void testAddingService() throws Exception {
+    public void testEndpointListenerService() throws Exception {
         LocalDiscovery ld = getLocalDiscovery();
-        ///
+
         Bundle bundle = EasyMock.createMock(Bundle.class);
         EasyMock.expect(bundle.getState()).andReturn(Bundle.ACTIVE);
         Dictionary<String, Object> headers = new Hashtable<String, Object>();
@@ -169,7 +204,7 @@
         BundleEvent be = new BundleEvent(BundleEvent.STARTED, bundle);
         ld.bundleChanged(be);
         assertEquals(2, ld.endpointDescriptions.size());        
-        ///
+
         final Hashtable<String, Object> props = new Hashtable<String, Object>();
         props.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, "(objectClass=org.example.ClassA)");
         ServiceReference sr = EasyMock.createMock(ServiceReference.class);
@@ -185,6 +220,7 @@
         EasyMock.reset(ld.bundleContext);
         EndpointListener el = EasyMock.createMock(EndpointListener.class);
         EasyMock.expect(ld.bundleContext.getService(sr)).andReturn(el);
+        EasyMock.expect(ld.bundleContext.ungetService(sr)).andReturn(true);
         EasyMock.expect(ld.bundleContext.createFilter((String) EasyMock.anyObject())).andAnswer(new
IAnswer<Filter>() {
             public Filter answer() throws Throwable {
                 return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]);
@@ -197,6 +233,7 @@
         EasyMock.expectLastCall();
         EasyMock.replay(el);
         
+        // Add the EndpointListener Service
         assertEquals("Precondition failed", 0, ld.listenerToFilters.size());
         assertEquals("Precondition failed", 0, ld.filterToListeners.size());        
         assertSame(el, ld.listenerTracker.addingService(sr));
@@ -207,14 +244,150 @@
         assertEquals(Collections.singletonList(el), ld.filterToListeners.get("(objectClass=org.example.ClassA)"));
 
         EasyMock.verify(el);
+        
+        // Modify the EndpointListener Service
+        // no need to reset the mock for this...
+        props.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, "(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))");
+        
+        EasyMock.reset(el);
+        final Set<String> actualEndpoints = new HashSet<String>();
+        el.endpointAdded((EndpointDescription) EasyMock.anyObject(), 
+                EasyMock.eq("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"));
+        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() throws Throwable {
+                EndpointDescription ed = (EndpointDescription) EasyMock.getCurrentArguments()[0];
+                actualEndpoints.addAll(ed.getInterfaces());
+                return null;
+            }
+        }).times(2);
+        EasyMock.replay(el);
+
+        ld.listenerTracker.modifiedService(sr, el);
+        assertEquals(1, ld.listenerToFilters.size());
+        assertEquals(Arrays.asList("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"),

+            ld.listenerToFilters.get(el));
+        assertEquals(2, ld.filterToListeners.size()); 
+        assertEquals(Collections.singletonList(el), 
+            ld.filterToListeners.get("(|(objectClass=org.example.ClassA)(objectClass=org.example.ClassB))"));
+        assertEquals(0, ld.filterToListeners.get("(objectClass=org.example.ClassA)").size());
+        
+        EasyMock.verify(el);
+        Set<String> expectedEndpoints = new HashSet<String>(Arrays.asList("org.example.ClassA",
"org.example.ClassB"));
+        assertEquals(expectedEndpoints, actualEndpoints);
+        
+        // Remove the EndpointListener Service
+        ld.listenerTracker.removedService(sr, el);
+        assertEquals(0, ld.listenerToFilters.size());
+        assertEquals(2, ld.filterToListeners.size());
+        Iterator<Collection<EndpointListener>> valIter = ld.filterToListeners.values().iterator();
+        assertEquals(0, valIter.next().size());
+        assertEquals(0, valIter.next().size());
     }
+    
+    public void testRegisterTracker() throws Exception {
+        LocalDiscovery ld = getLocalDiscovery();
 
-    private LocalDiscovery getLocalDiscovery() throws InvalidSyntaxException {
-        Filter filter = EasyMock.createMock(Filter.class);
-        EasyMock.replay(filter);
+        final Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, "(objectClass=Aaaa)");
+        ServiceReference sr = EasyMock.createMock(ServiceReference.class);
+        EasyMock.expect(sr.getPropertyKeys()).andReturn(props.keySet().toArray(new String
[] {})).anyTimes();
+        EasyMock.expect(sr.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>()
{
+            public Object answer() throws Throwable {
+                return props.get(EasyMock.getCurrentArguments()[0]);
+            }
+        }).anyTimes();                
+        EasyMock.replay(sr);
+
+        EndpointListener el = EasyMock.createMock(EndpointListener.class);
+        EasyMock.replay(el);
         
+        assertEquals("Precondition failed", 0, ld.listenerToFilters.size());
+        assertEquals("Precondition failed", 0, ld.filterToListeners.size());
+        ld.registerTracker(sr, el);
+        
+        assertEquals(1, ld.listenerToFilters.size());
+        assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(el));
+        assertEquals(1, ld.filterToListeners.size());
+        assertEquals(Collections.singletonList(el), ld.filterToListeners.get("(objectClass=Aaaa)"));
+        
+        // Add another one with the same scope filter
+        ServiceReference sr2 = EasyMock.createMock(ServiceReference.class);
+        EasyMock.expect(sr2.getPropertyKeys()).andReturn(props.keySet().toArray(new String
[] {})).anyTimes();
+        EasyMock.expect(sr2.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>()
{
+            public Object answer() throws Throwable {
+                return props.get(EasyMock.getCurrentArguments()[0]);
+            }
+        }).anyTimes();                
+        EasyMock.replay(sr2);
+
+        EndpointListener el2 = EasyMock.createMock(EndpointListener.class);
+        EasyMock.replay(el2);
+        ld.registerTracker(sr2, el2);
+
+        assertEquals(2, ld.listenerToFilters.size());
+        assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(el));
+        assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(el2));
+        
+        assertEquals(1, ld.filterToListeners.size());
+        assertEquals(Arrays.asList(el, el2), ld.filterToListeners.get("(objectClass=Aaaa)"));
+        
+        // Add another listener with a multi-value scope
+        final Hashtable<String, Object> props2 = new Hashtable<String, Object>();
+        props2.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, Arrays.asList("(objectClass=X)","(objectClass=Y)"));
+        ServiceReference sr3 = EasyMock.createMock(ServiceReference.class);
+        EasyMock.expect(sr3.getPropertyKeys()).andReturn(props2.keySet().toArray(new String
[] {})).anyTimes();
+        EasyMock.expect(sr3.getProperty((String) EasyMock.anyObject())).andAnswer(new IAnswer<Object>()
{
+            public Object answer() throws Throwable {
+                return props2.get(EasyMock.getCurrentArguments()[0]);
+            }
+        }).anyTimes();                
+        EasyMock.replay(sr3);
+
+        EndpointListener el3 = EasyMock.createMock(EndpointListener.class);
+        EasyMock.replay(el3);
+        ld.registerTracker(sr3, el3);
+
+        assertEquals(3, ld.listenerToFilters.size());
+        assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(el));
+        assertEquals(Collections.singletonList("(objectClass=Aaaa)"), ld.listenerToFilters.get(el2));
+        assertEquals(Arrays.asList("(objectClass=X)","(objectClass=Y)"), ld.listenerToFilters.get(el3));
+
+        assertEquals(3, ld.filterToListeners.size());
+        assertEquals(Arrays.asList(el, el2), ld.filterToListeners.get("(objectClass=Aaaa)"));
+        assertEquals(Collections.singletonList(el3), ld.filterToListeners.get("(objectClass=X)"));
+        assertEquals(Collections.singletonList(el3), ld.filterToListeners.get("(objectClass=Y)"));
+    }
+    
+    public void testClearTracker() throws Exception {
+        LocalDiscovery ld = getLocalDiscovery();
+        
+        EndpointListener el = EasyMock.createMock(EndpointListener.class);
+        ld.listenerToFilters.put(el, new ArrayList<String>(Arrays.asList("(a=b)", "(objectClass=foo.bar.Bheuaark)")));
+        ld.filterToListeners.put("(a=b)", new ArrayList<EndpointListener>(Arrays.asList(el)));
+        ld.filterToListeners.put("(objectClass=foo.bar.Bheuaark)", new ArrayList<EndpointListener>(Arrays.asList(el)));
+                        
+        ld.clearTracker("foobar"); // should not barf
+        
+        assertEquals(1, ld.listenerToFilters.size());
+        assertEquals(2, ld.filterToListeners.size());
+        assertEquals(1, ld.filterToListeners.values().iterator().next().size());
+        ld.clearTracker(EasyMock.createMock(EndpointListener.class));
+        assertEquals(1, ld.listenerToFilters.size());
+        assertEquals(2, ld.filterToListeners.size());
+        assertEquals(1, ld.filterToListeners.values().iterator().next().size());
+        ld.clearTracker(el);
+        assertEquals(0, ld.listenerToFilters.size());        
+        assertEquals(2, ld.filterToListeners.size());
+        assertEquals(0, ld.filterToListeners.values().iterator().next().size());
+    }    
+
+    private LocalDiscovery getLocalDiscovery() throws InvalidSyntaxException {
         BundleContext bc = EasyMock.createMock(BundleContext.class);
-        EasyMock.expect(bc.createFilter("(objectClass=org.osgi.service.remoteserviceadmin.EndpointListener)")).andReturn(filter);
+        EasyMock.expect(bc.createFilter((String) EasyMock.anyObject())).andAnswer(new IAnswer<Filter>()
{
+            public Filter answer() throws Throwable {
+                return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]);
+            }
+        }).anyTimes();
         bc.addServiceListener((ServiceListener) EasyMock.anyObject(), 
             EasyMock.eq("(objectClass=org.osgi.service.remoteserviceadmin.EndpointListener)"));
         EasyMock.expectLastCall();
@@ -226,5 +399,5 @@
                 
         LocalDiscovery ld = new LocalDiscovery(bc);
         return ld;
-    }
+    }    
 }



Mime
View raw message