You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by eg...@apache.org on 2008/11/06 18:20:22 UTC

svn commit: r711914 - in /cxf/sandbox/dosgi: dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/ dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/ felix/framework/src/main/java/...

Author: eglynn
Date: Thu Nov  6 09:18:55 2008
New Revision: 711914

URL: http://svn.apache.org/viewvc?rev=711914&view=rev
Log:
[dOSGi] Switch over to latest version of RFC 126 ListenerHook, on behalf of David Bosschaert (CXF-1896)

Added:
    cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java   (with props)
Modified:
    cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
    cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHook.java
    cxf/sandbox/dosgi/dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHookTest.java
    cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java
    cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
    cxf/sandbox/dosgi/felix/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
    cxf/sandbox/dosgi/systests/basic/src/test/java/org/apache/cxf/dosgi/systests/basic/ListenerHookSyncTest.java

Modified: cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java (original)
+++ cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/handlers/ServiceInvocationHandler.java Thu Nov  6 09:18:55 2008
@@ -55,13 +55,9 @@
                     }
                 }
             }
-            
-            // davidb temporary
-            throw new RuntimeException(theCause);
-            
-            // davidb TODO removed the following as it is not yet available in equinox
-//            throw new InvocationTargetException(
-//                      new ServiceException(REMOTE_EXCEPTION_TYPE, theCause));
+                        
+            throw new InvocationTargetException(
+                    new ServiceException(REMOTE_EXCEPTION_TYPE, theCause));
         }
     }
 

Modified: cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHook.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHook.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHook.java (original)
+++ cxf/sandbox/dosgi/dsw/cxf-dsw/src/main/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHook.java Thu Nov  6 09:18:55 2008
@@ -18,7 +18,9 @@
   */
 package org.apache.cxf.dosgi.dsw.hooks;
 
+import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 import java.util.logging.Logger;
 import java.util.regex.Matcher;
@@ -49,58 +51,38 @@
         SYSTEM_PACKAGES.add("org.ungoverned.osgi.service");
     }
     
-    private ThreadLocal<Boolean> findCallsInProgress
-        = new ThreadLocal<Boolean>() {
-             @Override
-             protected synchronized Boolean initialValue() {
-                 return Boolean.FALSE;
-             }
-         }; 
-    
     public CxfListenerHook(BundleContext bc, CxfDistributionProvider dp) {
         super(bc, dp);
     }
     
-    public void added(ListenerHook.Listener listener) {
-        handleListener(listener);
+    public void added(Collection /*<? extends ListenerHook.ListenerInfo>*/ listeners) {
+        handleListeners(listeners);
     }
 
-    public void initial(ListenerHook.Listener[] listeners) {
-        
-        if (isCallInProgress()) {
-            return;
-        }
-        
-        try {
-            setCallInProgress();
-            
-            for (ListenerHook.Listener listener : listeners) {
-                handleListener(listener);
-            }
-        } finally {
-            setCallCompleted();
-        }
+    public void removed(Collection /*<? extends ListenerHook.ListenerInfo>*/ listener) {
+        // todo add this in - need to unregister the endpoints
     }
 
-    public void removed(Listener listener) {
-    }
-
-    private void handleListener(Listener listener) {
-        if (listener.getFilter() == null
-            || listener.getBundleContext() == getContext()) {
-            return;
-        }
-        String className = getClassNameFromFilter(listener.getFilter());
-        if (!isClassSupported(className)) {
-            return;
+    private void handleListeners(Collection/*<? extends ListenerHook.ListenerInfo>*/ listeners) {
+        for (Iterator/*<? extends ListenerHook.ListenerInfo>*/ it = listeners.iterator(); it.hasNext(); ) {
+            ListenerHook.ListenerInfo listener = (ListenerHook.ListenerInfo) it.next();
+            
+            if (listener.getFilter() == null
+                    || listener.getBundleContext() == getContext()) {
+                    continue;
+                }
+                String className = getClassNameFromFilter(listener.getFilter());
+                if (!isClassSupported(className)) {
+                    continue;
+                }
+                
+                
+                processClientDescriptions(listener.getBundleContext(), 
+                                          className, 
+                                          listener.getFilter(), 
+                                          false, 
+                                          false);            
         }
-        
-        
-        processClientDescriptions(listener.getBundleContext(), 
-                                  className, 
-                                  listener.getFilter(), 
-                                  false, 
-                                  false);
     }
     
     private String getClassNameFromFilter(String filter) {
@@ -115,41 +97,6 @@
         return null;
     }
     
-    public void serviceReferencesRequested(BundleContext requestingContext,
-                                           String className,
-                                           String filter,
-                                           boolean allServices) {
-        
-        if (!isClassSupported(className)) {
-            return;
-        }
-        
-        if (isCallInProgress()) {
-            return;
-        }
-        try {
-            setCallInProgress();
-            processClientDescriptions(requestingContext, className, filter, false, allServices);
-        } finally {
-            setCallCompleted();
-        }
-        
-    }
-    
-    private Boolean isCallInProgress() {
-        return findCallsInProgress.get();
-    }
-    
-    private void setCallInProgress() {
-        findCallsInProgress.set(Boolean.TRUE);
-    }
-    
-    private void setCallCompleted() {
-        findCallsInProgress.set(Boolean.FALSE);
-    }
-    
-    
-    
     private static boolean isClassSupported(String className) {
         if (className == null) {
             return false;

Modified: cxf/sandbox/dosgi/dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHookTest.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHookTest.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHookTest.java (original)
+++ cxf/sandbox/dosgi/dsw/cxf-dsw/src/test/java/org/apache/cxf/dosgi/dsw/hooks/CxfListenerHookTest.java Thu Nov  6 09:18:55 2008
@@ -33,6 +33,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.service.ListenerHook;
 
 public class CxfListenerHookTest extends Assert {
 
@@ -43,6 +44,8 @@
         control = EasyMock.createNiceControl();
     }
     
+    /* Todo this test doesn't apply at the moment since the ListenerHook doesn't
+     * have a serviceReferencesRequested() API (yet).
     @Test
     public void testSyncListenerHook() throws Exception {
         
@@ -80,9 +83,52 @@
         List<ServiceReference> registeredRefs = dswContext.getRegisteredReferences();
         assertNotNull(registeredRefs);
         assertEquals(1, registeredRefs.size());        
-    }
+    } */
     
     @Test
+    public void testListenerHook() throws Exception {
+        
+        Bundle bundle = control.createMock(Bundle.class);
+        bundle.findEntries(EasyMock.eq("OSGI-INF/remote-services"), 
+            EasyMock.eq("*.xml"), EasyMock.anyBoolean());
+        EasyMock.expectLastCall().andReturn(Collections.enumeration(
+            Arrays.asList(getClass().getResource("/OSGI-INF/remote-services/remote-services.xml"))));
+        Dictionary<String, String> bundleHeaders = new Hashtable<String, String>();
+        bundleHeaders.put(org.osgi.framework.Constants.BUNDLE_NAME, 
+                          "Test Bundle");
+        bundleHeaders.put(org.osgi.framework.Constants.BUNDLE_VERSION, 
+                          "1.0.0");
+        bundle.getHeaders();
+        EasyMock.expectLastCall().andReturn(bundleHeaders).anyTimes();
+        bundle.loadClass(TestService.class.getName());
+        EasyMock.expectLastCall().andReturn(TestService.class).anyTimes();
+        final BundleContext requestingContext = control.createMock(BundleContext.class);
+        requestingContext.getBundle();
+        EasyMock.expectLastCall().andReturn(bundle).anyTimes();
+        
+        BundleTestContext dswContext = new BundleTestContext(bundle);
+        dswContext.addServiceReference(TestService.class.getName(), 
+                                       control.createMock(ServiceReference.class));
+        control.replay();
+     
+        CxfListenerHook hook = new CxfListenerHook(dswContext, null);
+        ListenerHook.ListenerInfo info = new ListenerHook.ListenerInfo() {
+            public BundleContext getBundleContext() {
+                return requestingContext;
+            }
+
+            public String getFilter() {
+                return "(objectClass=" + TestService.class.getName() + ")";
+            }            
+        };
+        hook.added(Collections.singleton(info));
+        
+        List<ServiceReference> registeredRefs = dswContext.getRegisteredReferences();
+        assertNotNull(registeredRefs);
+        assertEquals(1, registeredRefs.size());        
+    } 
+
+    @Test
     public void testConstructorAndGetters() {
         BundleContext bc = control.createMock(BundleContext.class);
         CxfDistributionProvider dp = control.createMock(CxfDistributionProvider.class);

Modified: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/Felix.java Thu Nov  6 09:18:55 2008
@@ -61,6 +61,7 @@
 import org.apache.felix.framework.searchpolicy.URLPolicyImpl;
 import org.apache.felix.framework.util.EventDispatcher;
 import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.ListenerHookInfoImpl;
 import org.apache.felix.framework.util.MapToDictionary;
 import org.apache.felix.framework.util.SecureAction;
 import org.apache.felix.framework.util.StringMap;
@@ -2687,9 +2688,7 @@
         m_dispatcher.addListener(
             bundle, ServiceListener.class, l, (f == null) ? null : new FilterImpl(m_logger, f));
         for (ListenerHook lHook : m_registry.getListenerHooks()) {
-            lHook.added(new ListenerHook.Listener(bundle.getBundleContext(),
-                                                  l,
-                                                  f));
+            lHook.added(Collections.singleton(new ListenerHookInfoImpl(bundle.getBundleContext(), f)));
         }
     }
 
@@ -2702,11 +2701,11 @@
     **/
     protected void removeServiceListener(Bundle bundle, ServiceListener l)
     {
-        ListenerHook.Listener listener = 
+        ListenerHook.ListenerInfo listener = 
             m_dispatcher.removeListener(bundle, ServiceListener.class, l);
         if (listener != null) {
             for (ListenerHook lHook : m_registry.getListenerHooks()) {
-                lHook.removed(listener);
+                lHook.removed(Collections.singleton(listener));
             }
         }
     }
@@ -2800,7 +2799,7 @@
         if (ListenerHook.class.isAssignableFrom(svcObj.getClass())
             && m_registry.hookRequested(classNames, ListenerHook.class.getName())) {
             ListenerHook lHook = (ListenerHook)svcObj;
-            lHook.initial(m_dispatcher.wrapAllServiceListeners());
+            lHook.added(m_dispatcher.wrapAllServiceListeners());
         }
         
         return reg;
@@ -2851,13 +2850,14 @@
         {
             return (ServiceReference[]) refList.toArray(new ServiceReference[refList.size()]);
         }
+        /* This API does not yet exist in RFC 126 
         for (ListenerHook lHook : m_registry.getListenerHooks()) {
             lHook.serviceReferencesRequested(bundle.getBundleContext(),
                                              className, 
                                              expr, 
                                              checkAssignable);
         }
-
+        */
         return null;
     }
 

Modified: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java (original)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java Thu Nov  6 09:18:55 2008
@@ -21,8 +21,10 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.EventListener;
 import java.util.EventObject;
+import java.util.List;
 
 import org.apache.felix.framework.Logger;
 import org.osgi.framework.AllServiceListener;
@@ -160,28 +162,27 @@
         }
     }
 
-    public ListenerHook.Listener[] wrapAllServiceListeners() {
+    public Collection<? extends ListenerHook.ListenerInfo> wrapAllServiceListeners() {
         Object[] listeners = null;
         synchronized (this)
         {
             listeners = m_serviceListeners;
         }
-        ListenerHook.Listener[] existingListeners = 
-            new ListenerHook.Listener[listeners.length/LISTENER_ARRAY_INCREMENT];
+
+        List<ListenerHook.ListenerInfo> existingListeners = new ArrayList<ListenerHook.ListenerInfo>();
         for (int i = 0, j = 0; i < listeners.length; i += LISTENER_ARRAY_INCREMENT, j++)
         {
-            existingListeners[j] = wrapListener(listeners, i);
+            existingListeners.add(wrapListener(listeners, i));
         }
         return existingListeners;
     }
     
-    private static ListenerHook.Listener wrapListener(Object[] listeners, int offset) {
+    private static ListenerHook.ListenerInfo wrapListener(Object[] listeners, int offset) {
         
         Filter filter = ((Filter)listeners[offset + LISTENER_FILTER_OFFSET]);
         
-        return new ListenerHook.Listener(
+        return new ListenerHookInfoImpl(
             ((Bundle)listeners[offset + LISTENER_BUNDLE_OFFSET]).getBundleContext(),
-            (ServiceListener)listeners[offset + LISTENER_OBJECT_OFFSET],
             filter == null ? null : filter.toString());
     }
     
@@ -293,9 +294,9 @@
 
     // returning ListenerHook.Listener is the only way to pick a filter value for the
     // service listener being removed. m_serviceListeners array can hold ListenerHook.Listener ?   
-    public ListenerHook.Listener removeListener(Bundle bundle, Class clazz, EventListener l)
+    public ListenerHook.ListenerInfo removeListener(Bundle bundle, Class clazz, EventListener l)
     {
-        ListenerHook.Listener listener = null;
+        ListenerHook.ListenerInfo listener = null;
         // Verify listener.
         if (l == null)
         {

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java?rev=711914&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java Thu Nov  6 09:18:55 2008
@@ -0,0 +1,40 @@
+/** 
+  * Licensed to the Apache Software Foundation (ASF) under one 
+  * or more contributor license agreements. See the NOTICE file 
+  * distributed with this work for additional information 
+  * regarding copyright ownership. The ASF licenses this file 
+  * to you under the Apache License, Version 2.0 (the 
+  * "License"); you may not use this file except in compliance 
+  * with the License. You may obtain a copy of the License at 
+  * 
+  * http://www.apache.org/licenses/LICENSE-2.0 
+  * 
+  * Unless required by applicable law or agreed to in writing, 
+  * software distributed under the License is distributed on an 
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
+  * KIND, either express or implied. See the License for the 
+  * specific language governing permissions and limitations 
+  * under the License. 
+  */
+package org.apache.felix.framework.util;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.hooks.service.ListenerHook;
+
+public class ListenerHookInfoImpl implements ListenerHook.ListenerInfo {
+    private final BundleContext bundleContext;
+    private final String filter;
+    
+    public ListenerHookInfoImpl(BundleContext bc, String f) {
+        bundleContext = bc;
+        filter = f;
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public String getFilter() {
+        return filter;
+    }
+}

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/util/ListenerHookInfoImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/sandbox/dosgi/felix/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java (original)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java Thu Nov  6 09:18:55 2008
@@ -17,40 +17,16 @@
  */
 package org.osgi.framework.hooks.service;
 
+import java.util.Collection;
+
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceListener;
 
 public interface ListenerHook {
-    static class Listener {
-        private BundleContext bc;
-        private ServiceListener sl;
-        private String filter;
-        
-        public Listener(BundleContext bc, ServiceListener sl, String filter) {
-            this.bc = bc;
-            this.sl = sl;
-            this.filter = filter;
-        }
-        
-        public BundleContext getBundleContext() {
-            return bc;
-        }
-        
-        public ServiceListener getServiceListener() {
-            return sl;
-        }
-        
-        public String getFilter() {
-            return filter;
-        }
+    public static interface ListenerInfo {
+        BundleContext getBundleContext();
+        String getFilter();
     }
     
-    void added(ListenerHook.Listener listener);
-    void initial(ListenerHook.Listener[] listeners);
-    void removed(ListenerHook.Listener listener);
-    
-    void serviceReferencesRequested(BundleContext bc,
-                                    String className,
-                                    String filter,
-                                    boolean allServices);
+    void added(Collection /* <? extends ListenerInfo> */ listeners);
+    void removed(Collection /* <? extends ListenerInfo> */ listener);
 }

Modified: cxf/sandbox/dosgi/systests/basic/src/test/java/org/apache/cxf/dosgi/systests/basic/ListenerHookSyncTest.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/systests/basic/src/test/java/org/apache/cxf/dosgi/systests/basic/ListenerHookSyncTest.java?rev=711914&r1=711913&r2=711914&view=diff
==============================================================================
--- cxf/sandbox/dosgi/systests/basic/src/test/java/org/apache/cxf/dosgi/systests/basic/ListenerHookSyncTest.java (original)
+++ cxf/sandbox/dosgi/systests/basic/src/test/java/org/apache/cxf/dosgi/systests/basic/ListenerHookSyncTest.java Thu Nov  6 09:18:55 2008
@@ -18,9 +18,11 @@
   */
 package org.apache.cxf.dosgi.systests.basic;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.jar.Manifest;
 
@@ -36,6 +38,7 @@
 import org.apache.servicemix.kernel.testing.support.AbstractIntegrationTest;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
 import org.springframework.osgi.test.platform.Platforms;
 
 public class ListenerHookSyncTest extends AbstractIntegrationTest  {
@@ -93,49 +96,81 @@
     }
     
     public void testBasicInvocation() throws Exception {
-
         Thread.currentThread().setContextClassLoader(ClientProxyFactoryBean.class.getClassLoader());
 
         Server server = null;
+        ServiceTracker st = null;
         try {
             server = startServer("http://localhost:9000/hello", 
                                  HelloService.class, new HelloServiceImpl());
-            ServiceReference sref = null;
-            for (int i = 0; i < 10; i++) {
-                sref = bundleContext.getServiceReference(HelloService.class.getName());
-                if (sref == null) {
-                    Thread.sleep(1000L);
+
+            final List srefs = new ArrayList();
+            st = new ServiceTracker(bundleContext, HelloService.class.getName(), null) {
+                public Object addingService(ServiceReference reference) {
+                    synchronized (srefs) {
+                        srefs.add(reference);
+                    }
+                    return super.addingService(reference);
+                }                
+            };
+            st.open();
+            
+            int loops = 0;
+            boolean found = false; 
+            while (!found && loops++ < 1000) {
+                synchronized (srefs) {
+                    found = srefs.size() > 0;
                 }
+                Thread.sleep(250);
             }
             
+            assertTrue("HelloService should have been registered once the service tracker was created", found);
+            ServiceReference sref = (ServiceReference) srefs.get(0);
             assertNotNull("HelloService reference is not available", sref);
             HelloService helloService = (HelloService)bundleContext.getService(sref);
             useService(helloService);
             
         } finally {
+            st.close();
             if (server != null) {
                 server.getDestination().shutdown();
                 server.stop();
             }
         }
         
+        st = null;
         server = null;
         try {
             server = startServer("http://localhost:9005/greeter", 
                                  GreeterService.class, new GreeterServiceImpl());
-            ServiceReference sref = null;
-            for (int i = 0; i < 10; i++) {
-                sref = bundleContext.getServiceReference(GreeterService.class.getName());
-                if (sref == null) {
-                    Thread.sleep(1000L);
+            final List srefs = new ArrayList();
+            st = new ServiceTracker(bundleContext, GreeterService.class.getName(), null) {
+                public Object addingService(ServiceReference reference) {
+                    synchronized (srefs) {
+                        srefs.add(reference);
+                    }
+                    return super.addingService(reference);
+                }                
+            };
+            st.open();
+            
+            int loops = 0;
+            boolean found = false; 
+            while (!found && loops++ < 1000) {
+                synchronized (srefs) {
+                    found = srefs.size() > 0;
                 }
+                Thread.sleep(250);
             }
-            
+                        
+            assertTrue("GreeterService should have been registered once the service tracker was created", found);
+            ServiceReference sref = (ServiceReference) srefs.get(0);
             assertNotNull("GreeterService reference is not available", sref);
             GreeterService greeterService = (GreeterService)bundleContext.getService(sref);
             useService(greeterService);
             
         } finally {
+            st.close();
             if (server != null) {
                 server.getDestination().shutdown();
                 server.stop();