You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by da...@apache.org on 2009/03/08 21:44:23 UTC

svn commit: r751516 - in /cxf/dosgi/trunk: discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/ discovery/local/src/test/java/ discovery/local/src/test/java/org/ discovery/local/src/test/java/org/apache/ discovery/local/src/test/java/org...

Author: davidb
Date: Sun Mar  8 20:44:22 2009
New Revision: 751516

URL: http://svn.apache.org/viewvc?rev=751516&view=rev
Log:
Added capability to local discovery service to scan any bundles for remote-services.xml files.

New unit tests included.

Added:
    cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/java/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/
    cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml   (with props)
    cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml   (with props)
Modified:
    cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryService.java
    cxf/dosgi/trunk/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/AbstractClientHook.java

Modified: cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryService.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryService.java?rev=751516&r1=751515&r2=751516&view=diff
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryService.java (original)
+++ cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryService.java Sun Mar  8 20:44:22 2009
@@ -20,6 +20,7 @@
 
 
 import static org.osgi.service.discovery.DiscoveredServiceNotification.AVAILABLE;
+import static org.osgi.service.discovery.DiscoveredServiceNotification.UNAVAILABLE;
 import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_FILTERS;
 import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_INTERFACES;
 
@@ -31,10 +32,14 @@
 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;
 
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
@@ -45,26 +50,25 @@
 import org.osgi.service.discovery.ServiceEndpointDescription;
 import org.osgi.util.tracker.ServiceTracker;
 
-@SuppressWarnings("unchecked")
-public class LocalDiscoveryService implements Discovery {
+public class LocalDiscoveryService implements Discovery, BundleListener {
     
     private static final Logger LOG = Logger.getLogger(LocalDiscoveryService.class.getName());
         
     // this is effectively a set which allows for multiple service descriptions with the
     // same interface name but different properties and takes care of itself with respect to concurrency 
-    private ConcurrentHashMap<ServiceEndpointDescription, ServiceEndpointDescription> servicesInfo = 
-        new ConcurrentHashMap<ServiceEndpointDescription, ServiceEndpointDescription>();
-    private Map<String, List<DiscoveredServiceTracker>> interfacesToTrackers = 
+    ConcurrentHashMap<ServiceEndpointDescription, Bundle> servicesInfo = 
+        new ConcurrentHashMap<ServiceEndpointDescription, Bundle>();
+    Map<String, List<DiscoveredServiceTracker>> interfacesToTrackers = 
         new HashMap<String, List<DiscoveredServiceTracker>>();
-    private Map<String, List<DiscoveredServiceTracker>> filtersToTrackers = 
+    Map<String, List<DiscoveredServiceTracker>> filtersToTrackers = 
         new HashMap<String, List<DiscoveredServiceTracker>>();
-    private Map<DiscoveredServiceTracker, Collection> trackersToInterfaces = 
-        new HashMap<DiscoveredServiceTracker, Collection>();
-    private Map<DiscoveredServiceTracker, Collection> trackersToFilters = 
-        new HashMap<DiscoveredServiceTracker, Collection>();
+    Map<DiscoveredServiceTracker, Collection<String>> trackersToInterfaces = 
+        new HashMap<DiscoveredServiceTracker, Collection<String>>();
+    Map<DiscoveredServiceTracker, Collection<String>> trackersToFilters = 
+        new HashMap<DiscoveredServiceTracker, Collection<String>>();
     private BundleContext bc;
         
-    private ServiceTracker trackerTracker;
+    ServiceTracker trackerTracker;
     
     public LocalDiscoveryService(BundleContext bc) {
         this.bc = bc;
@@ -94,9 +98,62 @@
             };
 
         trackerTracker.open();
+        
+        bc.addBundleListener(this);
+        // look at currently registered bundles.
+        processExistingBundles();
     }
 
-    public void updateProperties(Dictionary props) {
+    public void bundleChanged(BundleEvent be) {
+        LOG.info("bundle changed: " + be.getBundle().getSymbolicName());
+        switch (be.getType()) {
+        case BundleEvent.STARTED:
+            findDeclaredRemoteServices(be.getBundle());
+            break;
+        case BundleEvent.STOPPING:
+            removeServicesDeclaredInBundle(be.getBundle());
+            break;
+        }
+    }
+    
+    private void processExistingBundles() {
+        Bundle[] bundles = bc.getBundles();
+        if (bundles == null) {
+            return;
+        }
+        
+        for (Bundle b : bundles) {
+            if (b.getState() == Bundle.ACTIVE) {
+                findDeclaredRemoteServices(b);
+            }
+        }
+    }
+
+
+    private void findDeclaredRemoteServices(Bundle b) {
+        List<ServiceEndpointDescription> refs = LocalDiscoveryUtils.getAllRemoteReferences(b);
+        for(ServiceEndpointDescription sed : refs) {
+            servicesInfo.put(sed, b);
+            addedServiceDescription(sed);
+        }        
+    }    
+
+    private void removeServicesDeclaredInBundle(Bundle bundle) {
+        for(Iterator<Map.Entry<ServiceEndpointDescription, Bundle>> i = servicesInfo.entrySet().iterator(); i.hasNext(); ) {
+            Entry<ServiceEndpointDescription, Bundle> entry = i.next();
+            if (entry.getValue().equals(bundle)) {
+                removedServiceDescription(entry.getKey());
+                i.remove();
+            }            
+        }
+    }
+
+    private void addedServiceDescription(ServiceEndpointDescription sd) {
+        triggerCallbacks(sd, AVAILABLE);
+    }
+
+    private void removedServiceDescription(ServiceEndpointDescription sd) {
+        triggerCallbacks(sd, UNAVAILABLE);
     }
 
     private synchronized void cacheTracker(ServiceReference reference, 
@@ -104,13 +161,13 @@
         if (service instanceof DiscoveredServiceTracker) {
             DiscoveredServiceTracker tracker = 
                 (DiscoveredServiceTracker)service;
-            Collection interfaces =            
+            Collection<String> interfaces =            
                 addTracker(reference, 
                            tracker, 
                            PROP_KEY_MATCH_CRITERIA_INTERFACES, 
                            interfacesToTrackers,
                            trackersToInterfaces);
-            Collection filters = 
+            Collection<String> filters = 
                 addTracker(reference,
                            tracker, 
                            PROP_KEY_MATCH_CRITERIA_FILTERS, 
@@ -128,20 +185,20 @@
             DiscoveredServiceTracker tracker = 
                 (DiscoveredServiceTracker)service;
             LOG.info("updating tracker: " + tracker);
-            Collection oldInterfaces = removeTracker(tracker, 
+            Collection<String> oldInterfaces = removeTracker(tracker, 
                                                      interfacesToTrackers,
                                                      trackersToInterfaces);
-            Collection oldFilters = removeTracker(tracker, 
+            Collection<String> oldFilters = removeTracker(tracker, 
                                                   filtersToTrackers,
                                                   trackersToFilters);
 
-            Collection newInterfaces = 
+            Collection<String> newInterfaces = 
                 addTracker(reference, 
                            tracker, 
                            PROP_KEY_MATCH_CRITERIA_INTERFACES, 
                            interfacesToTrackers,
                            trackersToInterfaces);
-            Collection newFilters = 
+            Collection<String> newFilters = 
                 addTracker(reference,
                            tracker, 
                            PROP_KEY_MATCH_CRITERIA_FILTERS, 
@@ -164,20 +221,21 @@
         }
     }
 
-    private Collection addTracker(
+    @SuppressWarnings("unchecked")
+    private Collection<String> addTracker(
                       ServiceReference reference, 
                       DiscoveredServiceTracker tracker,
                       String property,
                       Map<String, List<DiscoveredServiceTracker>> forwardMap,
-                      Map<DiscoveredServiceTracker, Collection> reverseMap) {
-        Collection collection = 
-            (Collection)reference.getProperty(property);
+                      Map<DiscoveredServiceTracker, Collection<String>> reverseMap) {
+        Collection<String> collection = 
+            (Collection<String>) reference.getProperty(property);
         LOG.info("adding tracker: " + tracker + " collection: " + collection + " registered against prop: " + property);
         if (nonEmpty(collection)) {
             reverseMap.put(tracker, collection);
-            Iterator i = collection.iterator();
+            Iterator<String> i = collection.iterator();
             while (i.hasNext()) {
-                String element = (String)i.next();
+                String element = i.next();
                 if (forwardMap.containsKey(element)) {
                     forwardMap.get(element).add(tracker);
                 } else {
@@ -191,16 +249,16 @@
         return collection;
     }
 
-    private Collection removeTracker(
+    private Collection<String> removeTracker(
                       DiscoveredServiceTracker tracker,
                       Map<String, List<DiscoveredServiceTracker>> forwardMap,
-                      Map<DiscoveredServiceTracker, Collection> reverseMap) {
-        Collection collection = reverseMap.get(tracker);
+                      Map<DiscoveredServiceTracker, Collection<String>> reverseMap) {
+        Collection<String> collection = reverseMap.get(tracker);
         if (nonEmpty(collection)) {
             reverseMap.remove(tracker);
-            Iterator i = collection.iterator();
+            Iterator<String> i = collection.iterator();
             while (i.hasNext()) {
-                String element = (String)i.next();
+                String element = i.next();
                 if (forwardMap.containsKey(element)) {
                     forwardMap.get(element).remove(tracker);
                 }
@@ -208,20 +266,20 @@
         }
         return collection;
     }
-
-    private void triggerCallbacks(Collection oldInterest, 
-                                  Collection newInterest, 
+    
+    private void triggerCallbacks(Collection<String> oldInterest, 
+                                  Collection<String> newInterest, 
                                   DiscoveredServiceTracker tracker,
                                   boolean isFilter) {
         // compute delta between old & new interfaces/filters and
         // trigger callbacks for any entries in servicesInfo that
         // match any *additional* interface/filters  
-        Collection deltaInterest = new ArrayList();
+        Collection<String> deltaInterest = new ArrayList<String>();
         if (nonEmpty(newInterest)) {
             if (isEmpty(oldInterest)) {
                 deltaInterest.addAll(newInterest);
             } else {
-                Iterator i = newInterest.iterator();
+                Iterator<String> i = newInterest.iterator();
                 while (i.hasNext()) {
                     String next = (String)i.next();
                     if (!oldInterest.contains(next)) {
@@ -236,25 +294,44 @@
         } else {
             LOG.info("nothing to search for matches to trigger callbacks with delta: " + deltaInterest);
         }
-        Iterator i = deltaInterest.iterator();
+        Iterator<String> i = deltaInterest.iterator();
         while (i.hasNext()) {
-            String next = (String)i.next();
-            for (ServiceEndpointDescription sd : servicesInfo.values()) {
-                LOG.info("check if next: " + next + (isFilter ? " matches " : " contained by ") +  sd.getProvidedInterfaces());
-                if ((isFilter && filterMatches(next, sd))
-                    || sd.getProvidedInterfaces().contains(next)) {
-                    tracker.serviceChanged(new TrackerNotification(sd, 
-                                                                   AVAILABLE));
-                }
+            String next = i.next();
+            for (ServiceEndpointDescription sd : servicesInfo.keySet()) {
+                triggerCallbacks(tracker, next, isFilter, sd, AVAILABLE);
+            }
+        }        
+    }    
+
+    private void triggerCallbacks(ServiceEndpointDescription sd, int type) {
+        for (Map.Entry<DiscoveredServiceTracker, Collection<String>> entry : trackersToInterfaces.entrySet()) {
+            for (String match : entry.getValue()) {
+                triggerCallbacks(entry.getKey(), match, false, sd, type);
+            }
+        }
+        for (Map.Entry<DiscoveredServiceTracker, Collection<String>> entry : trackersToFilters.entrySet()) {
+            for (String match : entry.getValue()) {
+                triggerCallbacks(entry.getKey(), match, true, sd, type);
             }
         }
     }
 
-    private static boolean nonEmpty(Collection c) {
+    private void triggerCallbacks(DiscoveredServiceTracker tracker,
+                                  String match, boolean isFilter, 
+                                  ServiceEndpointDescription sd,
+                                  int notificationType) {
+        LOG.info("check if string: " + match + (isFilter ? " matches " : " contained by ") +  sd.getProvidedInterfaces());
+        if ((isFilter && filterMatches(match, sd))
+                || sd.getProvidedInterfaces().contains(match)) {
+            tracker.serviceChanged(new TrackerNotification(sd, notificationType));
+        }
+    }    
+
+    private static boolean nonEmpty(Collection<?> c) {
         return c != null && c.size() > 0;
     }
 
-    private static boolean isEmpty(Collection c) {
+    private static boolean isEmpty(Collection<?> c) {
         return c == null || c.size() == 0;
     }
 
@@ -279,6 +356,7 @@
     }
                 
     public void shutdown() {
+        bc.removeBundleListener(this);
         trackerTracker.close();
     }
         
@@ -318,14 +396,15 @@
         return d;
     }
     
+    @SuppressWarnings("unchecked")
     private static String[] getProvidedInterfaces(ServiceEndpointDescription sd, String interfaceName) {
         
-        Collection interfaceNames = sd.getProvidedInterfaces();
+        Collection<String> interfaceNames = sd.getProvidedInterfaces();
         if (interfaceName == null) {
             return null;
         }
         
-        Iterator iNames = interfaceNames.iterator();
+        Iterator<String> iNames = interfaceNames.iterator();
         while (iNames.hasNext()) {
             if (iNames.next().equals(interfaceName)) {
                 return new String[]{interfaceName};
@@ -333,5 +412,12 @@
         }
         return null;
     }
+
+    @SuppressWarnings("unchecked")
+    public void updateProperties(Dictionary props) {
+        // TODO can we get rid of the Config Admin stuff in here? 
+        // It doesn't seem to do anything with it...
+        // TODO Auto-generated method stub        
+    }
 }
     

Added: cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java (added)
+++ cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java Sun Mar  8 20:44:22 2009
@@ -0,0 +1,147 @@
+/** 
+  * 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.cxf.dosgi.discovery.local;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.Namespace;
+import org.jdom.input.SAXBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.service.discovery.ServiceEndpointDescription;
+
+
+public final class LocalDiscoveryUtils {
+    private static final Logger LOG = 
+        Logger.getLogger(LocalDiscoveryUtils.class.getName());        
+    
+    private static final String REMOTE_SERVICES_HEADER_NAME = "Remote-Service";
+    private static final String REMOTE_SERVICES_DIRECTORY =
+        "OSGI-INF/remote-service";
+    private static final String REMOTE_SERVICES_NS =
+        "http://www.osgi.org/xmlns/sd/v1.0.0";
+    
+    
+    private static final String SERVICE_DESCRIPTION_ELEMENT = "service-description";
+    
+    private static final String PROVIDE_INTERFACE_ELEMENT = "provide";
+    private static final String PROVIDE_INTERFACE_NAME_ATTRIBUTE = "interface";
+
+    private static final String PROPERTY_ELEMENT = "property";
+    private static final String PROPERTY_NAME_ATTRIBUTE = "name";
+    private static final String PROPERTY_VALUE_ATTRIBUTE = "value";
+    private static final String PROPERTY_INTERFACE_ATTRIBUTE = "interface";
+
+    private static final String INTERFACE_SEPARATOR = ":";
+    
+    private LocalDiscoveryUtils() {
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static List<ServiceEndpointDescription> getAllRemoteReferences(Bundle b) {
+        List<Element> references = getAllDescriptionElements(b);
+        
+        List<ServiceEndpointDescription> srefs = new ArrayList<ServiceEndpointDescription>();
+        Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
+        for (Element ref : references) {
+            List<String> iNames = getProvidedInterfaces(ref.getChildren(PROVIDE_INTERFACE_ELEMENT, ns));
+            Map<String, Object> remoteProps = getProperties(ref.getChildren(PROPERTY_ELEMENT, ns));
+            srefs.add(new ServiceEndpointDescriptionImpl(iNames, remoteProps));
+        }
+        return srefs;
+        
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static List<Element> getAllDescriptionElements(Bundle b) {
+        Object directory = null;
+        
+        Dictionary headers = b.getHeaders();
+        if (headers != null) {
+            directory = headers.get(REMOTE_SERVICES_HEADER_NAME);
+        }
+        
+        if (directory == null) {
+            directory = REMOTE_SERVICES_DIRECTORY;
+        }
+        
+        Enumeration urls = b.findEntries(directory.toString(), "*.xml", false);
+        if (urls == null) {
+            return Collections.emptyList();
+        }
+
+        List<Element> elements = new ArrayList<Element>();
+        while (urls.hasMoreElements()) {
+            URL resourceURL = (URL) urls.nextElement();
+            try {
+                Document d = new SAXBuilder().build(resourceURL.openStream());
+                Namespace ns = Namespace.getNamespace(REMOTE_SERVICES_NS);
+                elements.addAll(d.getRootElement().getChildren(SERVICE_DESCRIPTION_ELEMENT, ns));
+            } catch (Exception ex) {
+                LOG.log(Level.WARNING, "Problem parsing: " + resourceURL, ex);
+            }            
+        }
+        return elements; 
+    }
+    
+    private static Map<String, Object> getProperties(List<Element> elements) {       
+        Map<String, Object> props = new HashMap<String, Object>();
+        
+        for (Element p : elements) {
+            String key = p.getAttributeValue(PROPERTY_NAME_ATTRIBUTE);
+            String value = p.getAttributeValue(PROPERTY_VALUE_ATTRIBUTE);
+            if (value == null) {
+                value = p.getTextTrim();
+            }
+            
+            String iface = p.getAttributeValue(PROPERTY_INTERFACE_ATTRIBUTE);
+            if (key != null) {
+                props.put(iface == null || iface.length() == 0
+                          ? key
+                          : key + INTERFACE_SEPARATOR + iface,
+                          value);
+            }
+        }
+        
+        return props;
+    }
+    
+    private static List<String> getProvidedInterfaces(List<Element> elements) {        
+        List<String> names = new ArrayList<String>();
+        
+        for (Element p : elements) {
+            String name = p.getAttributeValue(PROVIDE_INTERFACE_NAME_ATTRIBUTE);
+            if (name != null) {
+                names.add(name);
+            }
+        }
+        
+        return names;
+    } 
+}

Propchange: cxf/dosgi/trunk/discovery/local/src/main/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryUtils.java
------------------------------------------------------------------------------
    svn:mergeinfo = 

Added: cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java Sun Mar  8 20:44:22 2009
@@ -0,0 +1,424 @@
+/** 
+  * 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.cxf.dosgi.discovery.local;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.easymock.IMocksControl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.discovery.DiscoveredServiceNotification;
+import org.osgi.service.discovery.DiscoveredServiceTracker;
+import org.osgi.service.discovery.ServiceEndpointDescription;
+
+public class LocalDiscoveryServiceTest extends TestCase {
+    public void testLocalDiscoveryServiceDSTInterface() {
+        URL rsA = getClass().getResource("/rs_a.xml");
+        Enumeration<URL> rsAEnum = Collections.enumeration(Arrays.asList(rsA));
+        URL rsB = getClass().getResource("/rs_b.xml");
+        Enumeration<URL> rsBEnum = Collections.enumeration(Arrays.asList(rsB));
+        URL rsC = getClass().getResource("/rs_c.xml");
+        Enumeration<URL> rsCEnum = Collections.enumeration(Arrays.asList(rsC));
+        
+        // Set up some mock objects
+        IMocksControl control = EasyMock.createNiceControl();
+        Bundle b0 = control.createMock(Bundle.class);
+        EasyMock.expect(b0.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b0.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsAEnum).anyTimes();
+        
+        BundleContext bc = control.createMock(BundleContext.class);
+        ServiceReference sr = control.createMock(ServiceReference.class);
+        TestDiscoveredServiceTracker dst = new TestDiscoveredServiceTracker();
+
+        EasyMock.expect(bc.getBundles()).andReturn(new Bundle[] {b0}).anyTimes();
+        EasyMock.expect(sr.getProperty("osgi.discovery.interest.interfaces")).
+                andReturn(Collections.singleton("org.example.SomeService")).anyTimes();
+        
+        EasyMock.expect(bc.getService(sr)).andReturn(dst).anyTimes();
+        control.replay();
+
+        // create the local discovery service
+        LocalDiscoveryService lds = new LocalDiscoveryService(bc);
+        
+        // it should be prepopulated with the info from bundle b0
+        assertEquals(2, lds.servicesInfo.size());
+        Map<String, Object> sed1Props = new HashMap<String, Object>();
+        sed1Props.put("osgi.remote.requires.intents", "confidentiality");
+        ServiceEndpointDescription sed1 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeService"), sed1Props);
+        ServiceEndpointDescription sed2 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("SomeOtherService", "WithSomeSecondInterface"));
+        assertTrue(lds.servicesInfo.containsKey(sed1));
+        assertTrue(lds.servicesInfo.containsKey(sed2));
+        
+        // should be pre-populated by now...
+        // register a tracker, it should get called back instantly with sed1
+        assertEquals("Precondition failed", 0, dst.notifications.size());
+        lds.trackerTracker.addingService(sr);
+        assertEquals(1, dst.notifications.size());
+        DiscoveredServiceNotification dsn = dst.notifications.iterator().next();
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, dsn.getType());
+        assertEquals(sed1, dsn.getServiceEndpointDescription());
+        
+        // add a new bundle that also contains a someservice 
+        // we should get notified again...
+        Bundle b1 = EasyMock.createNiceMock(Bundle.class);
+        EasyMock.expect(b1.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b1.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsBEnum).anyTimes();
+        EasyMock.replay(b1);
+
+        // Call back on the LDS just like what would have happened with the BundleListener 
+        BundleEvent be = new BundleEvent(BundleEvent.STARTED, b1);
+        lds.bundleChanged(be);
+        
+        ServiceEndpointDescription sed3 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeRelatedService", "org.example.SomeService"));
+        assertEquals(3, lds.servicesInfo.size());
+        assertTrue(lds.servicesInfo.containsKey(sed1));
+        assertTrue(lds.servicesInfo.containsKey(sed2));
+        assertTrue(lds.servicesInfo.containsKey(sed3));
+        
+        assertEquals("We should have been notified of the new bundle", 
+                2, dst.notifications.size());
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, 
+                dst.notifications.get(1).getType());
+        assertEquals(sed3, dst.notifications.get(1).getServiceEndpointDescription());
+        ArrayList<DiscoveredServiceNotification> copiedNotifications = 
+                new ArrayList<DiscoveredServiceNotification>(dst.notifications);
+        
+        // add an unrelated bundle - no notification...
+        Bundle b2 = EasyMock.createNiceMock(Bundle.class);
+        EasyMock.expect(b2.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b2.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsCEnum).anyTimes();
+        EasyMock.replay(b2);
+        
+        BundleEvent be2 = new BundleEvent(BundleEvent.STARTED, b1);
+        lds.bundleChanged(be2);
+        assertEquals("There should not have been any extra notification", 
+                copiedNotifications, dst.notifications);
+        
+        // Send an irrelevant bundle event
+        BundleEvent be3 = new BundleEvent(BundleEvent.LAZY_ACTIVATION, b0);        
+        lds.bundleChanged(be3);
+        assertEquals("There should not have been any changes to the registered serviceInfos",
+                3, lds.servicesInfo.size());
+        assertEquals("There should not have been any extra notification", 
+                copiedNotifications, dst.notifications);
+               
+        // remove bundle b0
+        BundleEvent be4 = new BundleEvent(BundleEvent.STOPPING, b0);        
+        lds.bundleChanged(be4);
+        
+        assertEquals(1, lds.servicesInfo.size());
+        assertEquals(sed3, lds.servicesInfo.keySet().iterator().next());
+        
+        assertEquals(3, dst.notifications.size()); 
+        assertEquals(DiscoveredServiceNotification.UNAVAILABLE, 
+                dst.notifications.get(2).getType());
+        assertEquals(sed1, dst.notifications.get(2).getServiceEndpointDescription());
+
+        // now remove the tracker itself...
+        assertEquals("Precondition failed", 1, lds.interfacesToTrackers.size());
+        assertEquals("Precondition failed", 1, lds.trackersToInterfaces.size());
+        assertEquals("Precondition failed", 1, lds.interfacesToTrackers.values().iterator().next().size());
+        assertEquals("Precondition failed", 1, lds.trackersToInterfaces.values().iterator().next().size());
+        lds.trackerTracker.removedService(sr, dst);
+        assertEquals("Tracker should have been removed", 0, lds.interfacesToTrackers.values().iterator().next().size());
+        assertEquals("Tracker should have been removed", 0, lds.trackersToInterfaces.size());
+    }
+    
+    public void testLocalDiscoveryServiceDSTFilter() throws Exception {
+        URL rsA = getClass().getResource("/rs_d.xml");
+        Enumeration<URL> rsAEnum = Collections.enumeration(Arrays.asList(rsA));
+        URL rsB = getClass().getResource("/rs_e.xml");
+        Enumeration<URL> rsBEnum = Collections.enumeration(Arrays.asList(rsB));
+        URL rsC = getClass().getResource("/rs_f.xml");
+        Enumeration<URL> rsCEnum = Collections.enumeration(Arrays.asList(rsC));
+        
+        // Set up some mock objects
+        IMocksControl control = EasyMock.createNiceControl();
+        Bundle b0 = control.createMock(Bundle.class);
+        EasyMock.expect(b0.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b0.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsAEnum).anyTimes();
+        
+        BundleContext bc = control.createMock(BundleContext.class);
+        Filter mockFilter = control.createMock(Filter.class);
+        ServiceReference sr = control.createMock(ServiceReference.class);
+        TestDiscoveredServiceTracker dst = new TestDiscoveredServiceTracker();
+
+        EasyMock.expect(bc.getBundles()).andReturn(new Bundle[] {b0}).anyTimes();
+        EasyMock.expect(bc.createFilter("(blah <= 5)")).andReturn(mockFilter).anyTimes();
+        EasyMock.expect(sr.getProperty("osgi.discovery.interest.filters")).
+                andReturn(Collections.singleton("(blah <= 5)")).anyTimes();
+        
+        EasyMock.expect(bc.getService(sr)).andReturn(dst).anyTimes();
+        
+        // set up the mock filter behaviour
+        Dictionary<String, Object> d1 = new Hashtable<String, Object>();
+        d1.put("blah", "5");
+        EasyMock.expect(mockFilter.match(d1)).andReturn(true).anyTimes();
+        Dictionary<String, Object> d2 = new Hashtable<String, Object>();
+        d2.put("blah", "3");
+        d2.put("boo", "hello");
+        EasyMock.expect(mockFilter.match(d2)).andReturn(true).anyTimes();
+        
+        control.replay();
+
+        // create the local discovery service
+        LocalDiscoveryService lds = new LocalDiscoveryService(bc);
+        
+        // it should be prepopulated with the info from bundle b0
+        assertEquals(2, lds.servicesInfo.size());
+        Map<String, Object> sed1Props = new HashMap<String, Object>();
+        sed1Props.put("osgi.remote.requires.intents", "confidentiality");
+        ServiceEndpointDescription sed1 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeService"), sed1Props);
+        Map<String, Object> sed2Props = new HashMap<String, Object>();
+        sed2Props.put("blah", "5");
+        ServiceEndpointDescription sed2 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("SomeOtherService", "WithSomeSecondInterface"), sed2Props);
+        assertTrue(lds.servicesInfo.containsKey(sed1));
+        assertTrue(lds.servicesInfo.containsKey(sed2));
+        
+        // should be pre-populated by now...
+        // register a tracker, it should get called back instantly with sed1
+        assertEquals("Precondition failed", 0, dst.notifications.size());
+        lds.trackerTracker.addingService(sr);
+        assertEquals(1, dst.notifications.size());
+        DiscoveredServiceNotification dsn = dst.notifications.iterator().next();
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, dsn.getType());
+        assertEquals(sed2, dsn.getServiceEndpointDescription());
+        
+        // add a new bundle that also contains a someservice 
+        // we should get notified again...
+        Bundle b1 = EasyMock.createNiceMock(Bundle.class);
+        EasyMock.expect(b1.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b1.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsBEnum).anyTimes();
+        EasyMock.replay(b1);
+
+        // Call back on the LDS just like what would have happened with the BundleListener 
+        BundleEvent be = new BundleEvent(BundleEvent.STARTED, b1);
+        lds.bundleChanged(be);
+        
+        Map<String, Object> sed3Props = new HashMap<String, Object>();
+        sed3Props.put("blah", "3");
+        sed3Props.put("boo", "hello");
+        ServiceEndpointDescription sed3 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeRelatedService", "org.example.SomeService"), sed3Props);
+        assertEquals(3, lds.servicesInfo.size());
+        assertTrue(lds.servicesInfo.containsKey(sed1));
+        assertTrue(lds.servicesInfo.containsKey(sed2));
+        assertTrue(lds.servicesInfo.containsKey(sed3));
+        
+        assertEquals("We should have been notified of the new bundle", 
+                2, dst.notifications.size());
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, 
+                dst.notifications.get(1).getType());
+        assertEquals(sed3, dst.notifications.get(1).getServiceEndpointDescription());
+        ArrayList<DiscoveredServiceNotification> copiedNotifications = 
+                new ArrayList<DiscoveredServiceNotification>(dst.notifications);
+        
+        // add an unrelated bundle - no notification...
+        Bundle b2 = EasyMock.createNiceMock(Bundle.class);
+        EasyMock.expect(b2.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b2.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsCEnum).anyTimes();
+        EasyMock.replay(b2);
+        
+        BundleEvent be2 = new BundleEvent(BundleEvent.STARTED, b1);
+        lds.bundleChanged(be2);
+        assertEquals("There should not have been any extra notification", 
+                copiedNotifications, dst.notifications);
+        
+        // assert that we get notified about the removal
+    }
+
+    public void testUpdateTracker() {
+        URL rsA = getClass().getResource("/rs_a.xml");
+        Enumeration<URL> rsAEnum = Collections.enumeration(Arrays.asList(rsA));
+        
+        // Set up some mock objects
+        IMocksControl control = EasyMock.createNiceControl();
+        Bundle b0 = control.createMock(Bundle.class);
+        EasyMock.expect(b0.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b0.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsAEnum).anyTimes();
+        
+        BundleContext bc = control.createMock(BundleContext.class);
+        EasyMock.expect(bc.getBundles()).andReturn(new Bundle[] {b0}).anyTimes();
+
+        TestDiscoveredServiceTracker dst = new TestDiscoveredServiceTracker();
+
+        ServiceReference sr = EasyMock.createNiceMock(ServiceReference.class);
+        EasyMock.expect(sr.getProperty("osgi.discovery.interest.interfaces")).
+                andReturn(Collections.singleton("org.example.SomeService")).anyTimes();
+        EasyMock.replay(sr);
+        
+        EasyMock.expect(bc.getService(sr)).andReturn(dst).anyTimes();
+        control.replay();
+
+        // create the local discovery service
+        LocalDiscoveryService lds = new LocalDiscoveryService(bc);
+        
+        // it should be prepopulated with the info from bundle b0
+        assertEquals(2, lds.servicesInfo.size());
+        Map<String, Object> sed1Props = new HashMap<String, Object>();
+        sed1Props.put("osgi.remote.requires.intents", "confidentiality");
+        ServiceEndpointDescription sed1 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeService"), sed1Props);
+        ServiceEndpointDescription sed2 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("SomeOtherService", "WithSomeSecondInterface"));
+        assertTrue(lds.servicesInfo.containsKey(sed1));
+        assertTrue(lds.servicesInfo.containsKey(sed2));
+        
+        // should be prepopulated by now...
+        // register a tracker, it should get called back instantly with sed1
+        assertEquals("Precondition failed", 0, dst.notifications.size());
+        lds.trackerTracker.addingService(sr);
+        assertEquals(1, dst.notifications.size());
+        DiscoveredServiceNotification dsn = dst.notifications.iterator().next();
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, dsn.getType());
+        assertEquals(sed1, dsn.getServiceEndpointDescription());
+        
+        EasyMock.reset(sr);
+        EasyMock.expect(sr.getProperty("osgi.discovery.interest.interfaces")).
+                andReturn(Arrays.asList("org.example.SomeService", "SomeOtherService")).anyTimes();
+        EasyMock.replay(sr);
+        
+        lds.trackerTracker.modifiedService(sr, dst);
+        assertEquals(2, dst.notifications.size());
+        DiscoveredServiceNotification dsn0 = dst.notifications.get(0);
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, dsn0.getType());
+        assertEquals(sed1, dsn0.getServiceEndpointDescription());
+        DiscoveredServiceNotification dsn1 = dst.notifications.get(1);
+        assertEquals(DiscoveredServiceNotification.AVAILABLE, dsn1.getType());
+        assertEquals(sed2, dsn1.getServiceEndpointDescription());        
+    }
+    
+    public void testLocalDiscoveryServiceExistingBundles() {
+        URL rsA = getClass().getResource("/rs_a.xml");
+        Enumeration<URL> rsAEnum = Collections.enumeration(Arrays.asList(rsA));
+        URL rsB = getClass().getResource("/rs_b.xml");
+        Enumeration<URL> rsBEnum = Collections.enumeration(Arrays.asList(rsB));
+        
+        // Set up some mock objects
+        IMocksControl control = EasyMock.createNiceControl();
+        Bundle b0 = control.createMock(Bundle.class);
+        EasyMock.expect(b0.getState()).andReturn(Bundle.INSTALLED).anyTimes();
+        EasyMock.expect(b0.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsAEnum).anyTimes();
+
+        Bundle b1 = control.createMock(Bundle.class);
+        EasyMock.expect(b1.getState()).andReturn(Bundle.ACTIVE).anyTimes();
+        EasyMock.expect(b1.findEntries("OSGI-INF/remote-service", "*.xml", false)).
+                andReturn(rsBEnum).anyTimes();
+        
+        BundleContext bc = control.createMock(BundleContext.class);
+        ServiceReference sr = control.createMock(ServiceReference.class);
+        TestDiscoveredServiceTracker dst = new TestDiscoveredServiceTracker();
+
+        EasyMock.expect(bc.getBundles()).andReturn(new Bundle[] {b0, b1}).anyTimes();
+        EasyMock.expect(sr.getProperty("osgi.discovery.interest.interfaces")).
+                andReturn(Collections.singleton("org.example.SomeService")).anyTimes();
+        
+        EasyMock.expect(bc.getService(sr)).andReturn(dst).anyTimes();
+        control.replay();
+
+        // create the local discovery service
+        LocalDiscoveryService lds = new LocalDiscoveryService(bc);
+        
+        ServiceEndpointDescription sed3 = new ServiceEndpointDescriptionImpl(
+                Arrays.asList("org.example.SomeRelatedService", "org.example.SomeService"));
+        assertEquals(1, lds.servicesInfo.size());
+        assertEquals(sed3, lds.servicesInfo.keySet().iterator().next());
+    
+    }
+    
+    public void testCombinationInterfaceAndFilter() {
+        // TODO write this one
+    }
+    
+    public void testCreatThenShutdown() {
+        final List<String> bundleListenerRegs = new ArrayList<String>();
+        
+        IMocksControl control = EasyMock.createNiceControl();
+        BundleContext bc = control.createMock(BundleContext.class);
+        bc.addBundleListener((BundleListener) EasyMock.anyObject());
+        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() throws Throwable {
+                assertTrue("Should be a LocalDiscoveryService", 
+                        EasyMock.getCurrentArguments()[0] instanceof LocalDiscoveryService);
+                bundleListenerRegs.add("addBundleListener");
+                return null;
+            }            
+        });
+        
+        bc.removeBundleListener((BundleListener) EasyMock.anyObject());
+        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() throws Throwable {
+                assertTrue("Should be a LocalDiscoveryService", 
+                        EasyMock.getCurrentArguments()[0] instanceof LocalDiscoveryService);
+                bundleListenerRegs.add("removeBundleListener");
+                return null;
+            }            
+        });
+        
+        control.replay();
+        
+        assertEquals("Precondition failed", 0, bundleListenerRegs.size());
+        LocalDiscoveryService lds = new LocalDiscoveryService(bc);
+        assertEquals(1, bundleListenerRegs.size());
+        assertEquals("addBundleListener", bundleListenerRegs.get(0));
+        
+        lds.shutdown();
+        assertEquals(2, bundleListenerRegs.size());
+        assertEquals("addBundleListener", bundleListenerRegs.get(0));
+        assertEquals("removeBundleListener", bundleListenerRegs.get(1));
+    }
+
+    private static class TestDiscoveredServiceTracker implements DiscoveredServiceTracker {
+        private List<DiscoveredServiceNotification> notifications = new ArrayList<DiscoveredServiceNotification>();
+
+        public void serviceChanged(DiscoveredServiceNotification notification) {
+            notifications.add(notification);
+        }        
+    }
+}

Propchange: cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/dosgi/trunk/discovery/local/src/test/java/org/apache/cxf/dosgi/discovery/local/LocalDiscoveryServiceTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeService" />
+    <property name="osgi.remote.requires.intents">confidentiality</property>
+  </service-description>
+  <service-description>
+    <provide interface="SomeOtherService" />
+    <provide interface="WithSomeSecondInterface" />
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_a.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeRelatedService" />
+    <provide interface="org.example.SomeService" />
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_b.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeThirdPartyService" />
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_c.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeService" />
+    <property name="osgi.remote.requires.intents">confidentiality</property>
+  </service-description>
+  <service-description>
+    <provide interface="SomeOtherService" />
+    <provide interface="WithSomeSecondInterface" />
+    <property name="blah">5</property>
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_d.xml
------------------------------------------------------------------------------
    svn:mergeinfo = 

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeRelatedService" />
+    <provide interface="org.example.SomeService" />
+    <property name="blah" value="3" />
+    <property name="boo" value="hello" />
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_e.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml?rev=751516&view=auto
==============================================================================
--- cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml (added)
+++ cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml Sun Mar  8 20:44:22 2009
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<service-descriptions xmlns="http://www.osgi.org/xmlns/sd/v1.0.0">
+  <service-description>
+    <provide interface="org.example.SomeThirdPartyService" />
+    <property name="blah">15</property>
+  </service-description>
+</service-descriptions>

Propchange: cxf/dosgi/trunk/discovery/local/src/test/resources/rs_f.xml
------------------------------------------------------------------------------
    svn:mergeinfo = 

Modified: cxf/dosgi/trunk/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/AbstractClientHook.java
URL: http://svn.apache.org/viewvc/cxf/dosgi/trunk/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/AbstractClientHook.java?rev=751516&r1=751515&r2=751516&view=diff
==============================================================================
--- cxf/dosgi/trunk/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/AbstractClientHook.java (original)
+++ cxf/dosgi/trunk/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/AbstractClientHook.java Sun Mar  8 20:44:22 2009
@@ -18,34 +18,30 @@
   */
 package org.apache.cxf.dosgi.dsw.hooks;
 
+import static org.osgi.service.discovery.DiscoveredServiceNotification.AVAILABLE;
+import static org.osgi.service.discovery.DiscoveredServiceNotification.MODIFIED;
+import static org.osgi.service.discovery.DiscoveredServiceNotification.UNAVAILABLE;
+import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_FILTERS;
+import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_INTERFACES;
+
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 
 import org.apache.cxf.dosgi.dsw.Constants;
-import org.apache.cxf.dosgi.dsw.OsgiUtils;
 import org.apache.cxf.dosgi.dsw.handlers.ClientServiceFactory;
 import org.apache.cxf.dosgi.dsw.handlers.ConfigurationTypeHandler;
 import org.apache.cxf.dosgi.dsw.service.CxfDistributionProvider;
-
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.discovery.ServiceEndpointDescription;
-import org.osgi.service.discovery.DiscoveredServiceTracker;
 import org.osgi.service.discovery.DiscoveredServiceNotification;
-
-import static org.osgi.service.discovery.DiscoveredServiceNotification.AVAILABLE;
-import static org.osgi.service.discovery.DiscoveredServiceNotification.MODIFIED;
-import static org.osgi.service.discovery.DiscoveredServiceNotification.UNAVAILABLE;
-import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_FILTERS;
-import static org.osgi.service.discovery.DiscoveredServiceTracker.PROP_KEY_MATCH_CRITERIA_INTERFACES;
+import org.osgi.service.discovery.DiscoveredServiceTracker;
+import org.osgi.service.discovery.ServiceEndpointDescription;
 
 
 public class AbstractClientHook extends AbstractHook {
@@ -69,9 +65,10 @@
                                              String interfaceName, 
                                              String filter) {
         
-        if (!lookupCurrentBundle(requestingContext, interfaceName, filter)) {
-            lookupDiscoveryService(interfaceName, filter);
-        }
+        lookupDiscoveryService(interfaceName, filter);
+//        if (!lookupCurrentBundle(requestingContext, interfaceName, filter)) {
+//            lookupDiscoveryService(interfaceName, filter);
+//        }
     }
     
     protected void processServiceDescription(ServiceEndpointDescription sd,
@@ -130,6 +127,7 @@
         return props;
     }
 
+    /*
     protected synchronized boolean lookupCurrentBundle(BundleContext context, 
                                                        String interfaceName, 
                                                        String filter) {     
@@ -152,9 +150,8 @@
             }
         }
         return sds.size() > 0;
-    }
+    } */
 
-    @SuppressWarnings("unchecked")
     protected synchronized void lookupDiscoveryService(String interfaceName, String filterValue) {
 
         if (interfaceName != null) {