You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2013/03/07 12:36:42 UTC

svn commit: r1453783 - in /aries/trunk/util/util-r42/src: main/java/org/apache/aries/util/tracker/SingleServiceTracker.java test/java/org/apache/aries/util/SingleServiceTrackerTest.java

Author: timothyjward
Date: Thu Mar  7 11:36:41 2013
New Revision: 1453783

URL: http://svn.apache.org/r1453783
Log:
ARIES-1024 : Fix SingleServiceTracker so that it finds pre-registered services properly when using a filter

Modified:
    aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/tracker/SingleServiceTracker.java
    aries/trunk/util/util-r42/src/test/java/org/apache/aries/util/SingleServiceTrackerTest.java

Modified: aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/tracker/SingleServiceTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/tracker/SingleServiceTracker.java?rev=1453783&r1=1453782&r2=1453783&view=diff
==============================================================================
--- aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/tracker/SingleServiceTracker.java (original)
+++ aries/trunk/util/util-r42/src/main/java/org/apache/aries/util/tracker/SingleServiceTracker.java Thu Mar  7 11:36:41 2013
@@ -23,7 +23,7 @@ import java.util.concurrent.atomic.Atomi
 
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
@@ -45,7 +45,7 @@ public final class SingleServiceTracker<
   private final AtomicBoolean open = new AtomicBoolean(false);
   private final SingleServiceListener serviceListener;
   private String filterString;
-  private Filter filter;
+  private boolean isCustomFilter;
 
   private final ServiceListener listener = new ServiceListener()
   {
@@ -69,13 +69,17 @@ public final class SingleServiceTracker<
     ctx = context;
     this.className = clazz.getName();
     serviceListener = sl;
+    this.filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
   }
   
   public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException
   {
     this(context, clazz, sl);
-    this.filterString = filterString;
-    if (filterString != null) filter = context.createFilter(filterString);
+    if (filterString != null) {
+    	this.filterString = "(&" + this.filterString + filterString + ')';
+    	isCustomFilter = true;
+    }
+    FrameworkUtil.createFilter(this.filterString);
   }
   
   public T getService()
@@ -92,8 +96,6 @@ public final class SingleServiceTracker<
   {
     if (open.compareAndSet(false, true)) {
       try {
-        String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')';
-        if (filter != null) filterString = "(&" + filterString + filter + ')';
         ctx.addServiceListener(listener, filterString);
         findMatchingReference(null);
       } catch (InvalidSyntaxException e) {
@@ -104,8 +106,23 @@ public final class SingleServiceTracker<
 
   private void findMatchingReference(ServiceReference original) {
     boolean clear = true;
-    ServiceReference ref = ctx.getServiceReference(className);
-    if (ref != null && (filter == null || filter.match(ref))) {
+    ServiceReference ref;
+    if(isCustomFilter) {
+      try {
+        ServiceReference[] refs = ctx.getServiceReferences(className, filterString);
+        if(refs == null || refs.length == 0) {
+          ref = null;
+        } else {
+    	  ref = refs[0];
+        }
+      } catch (InvalidSyntaxException e) {
+        //This can't happen, we'd have blown up in the constructor
+        ref = null;
+      }
+    } else {
+	  ref = ctx.getServiceReference(className);
+    }
+    if (ref != null) {
       @SuppressWarnings("unchecked")
       T service = (T) ctx.getService(ref);
       if (service != null) {

Modified: aries/trunk/util/util-r42/src/test/java/org/apache/aries/util/SingleServiceTrackerTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/util/util-r42/src/test/java/org/apache/aries/util/SingleServiceTrackerTest.java?rev=1453783&r1=1453782&r2=1453783&view=diff
==============================================================================
--- aries/trunk/util/util-r42/src/test/java/org/apache/aries/util/SingleServiceTrackerTest.java (original)
+++ aries/trunk/util/util-r42/src/test/java/org/apache/aries/util/SingleServiceTrackerTest.java Thu Mar  7 11:36:41 2013
@@ -18,6 +18,10 @@
  */
 package org.apache.aries.util;
 
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
 import org.apache.aries.mocks.BundleContextMock;
 import org.apache.aries.unittest.mocks.MethodCall;
 import org.apache.aries.unittest.mocks.Skeleton;
@@ -27,6 +31,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
 
 import static org.junit.Assert.*;
 
@@ -46,12 +51,68 @@ public class SingleServiceTrackerTest {
   }
   
   private void createSut() {
+	  createSut(null);
+  }
+  
+  private void createSut(String filter) {
     listener = Skeleton.newMock(SingleServiceListener.class);
-    sut = new SingleServiceTracker<String>(ctx, String.class, listener);
+    try {
+		sut = new SingleServiceTracker<String>(ctx, String.class, filter, listener);
+	} catch (InvalidSyntaxException e) {
+		throw new RuntimeException(e);
+	}
     sut.open();
   }
   
   @Test
+  public void testBeforeTheFactService() {
+	  ctx.registerService("java.lang.String", "uno", null);
+	  createSut();
+	  Skeleton.getSkeleton(listener).assertCalled(Arrays.asList(new MethodCall(SingleServiceListener.class, "serviceFound")), true);
+	  assertEquals("uno", sut.getService());
+  }
+  
+  @Test
+  public void testBeforeTheFactServiceDoubleRegistration() {
+	  testBeforeTheFactService();
+	  
+	  ctx.registerService("java.lang.String", "due", null);
+	  Skeleton.getSkeleton(listener).assertCalled(Arrays.asList(new MethodCall(SingleServiceListener.class, "serviceFound")), true);
+	  assertEquals("uno", sut.getService());
+  }
+  
+  @Test
+  public void testBeforeTheFactChoice() {
+	  ctx.registerService("java.lang.String", "uno", null);
+	  ctx.registerService("java.lang.String", "due", null);
+	  createSut();
+	  Skeleton.getSkeleton(listener).assertCalled(Arrays.asList(new MethodCall(SingleServiceListener.class, "serviceFound")), true);
+	  assertEquals("uno", sut.getService());
+  }
+  
+  @Test
+  public void testBeforeTheFactChoiceWithPropertiesAndFilterWithFirstMatch() {
+	  Dictionary<String, String> props = new Hashtable<String, String>();
+	  props.put("foo", "bar");
+	  ctx.registerService("java.lang.String", "uno", props);
+	  ctx.registerService("java.lang.String", "due", null);
+	  createSut("(foo=bar)");
+	  Skeleton.getSkeleton(listener).assertCalled(Arrays.asList(new MethodCall(SingleServiceListener.class, "serviceFound")), true);
+	  assertEquals("uno", sut.getService());
+  }
+  
+  @Test
+  public void testBeforeTheFactChoiceWithPropertiesAndFilterWithSecondMatch() {
+	  Dictionary<String, String> props = new Hashtable<String, String>();
+	  props.put("foo", "bar");
+	  ctx.registerService("java.lang.String", "uno", null);
+	  ctx.registerService("java.lang.String", "due", props);
+	  createSut("(foo=bar)");
+	  Skeleton.getSkeleton(listener).assertCalled(Arrays.asList(new MethodCall(SingleServiceListener.class, "serviceFound")), true);
+	  assertEquals("due", sut.getService());
+  }
+  
+  @Test
   public void testAfterTheFactService() 
   {
     createSut();