FELIX-3481 Add tests for the matchesTarget method and improve the MockBundle to throw an AbstractMethodError if one of the post-Framework-API-1.4 methods is called, such as Bundle.getVersion().

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1356274 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/helper/TargetedPID.java b/configadmin/src/main/java/org/apache/felix/cm/impl/helper/TargetedPID.java
index 2d31da5..b50fc6d 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/helper/TargetedPID.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/helper/TargetedPID.java
@@ -22,6 +22,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 
 
 /**
@@ -110,32 +111,35 @@
      */
     public boolean matchesTarget( ServiceReference<?> reference )
     {
+        // already unregistered
+        final Bundle serviceBundle = reference.getBundle();
+        if ( serviceBundle == null )
+        {
+            return false;
+        }
+
         // This is not really targeted
         if ( this.symbolicName == null )
         {
             return true;
         }
 
-        final Bundle serviceBundle = reference.getBundle();
-
-        // already unregistered
-        if ( serviceBundle == null )
-        {
-            return false;
-        }
-
         // bundle symbolic names don't match
         if ( !this.symbolicName.equals( serviceBundle.getSymbolicName() ) )
         {
             return false;
         }
 
-        // assert version match
+        // no more specific target
         if ( this.version == null )
         {
             return true;
         }
-        else if ( !this.version.equals( serviceBundle.getVersion().toString() ) )
+
+        // bundle version does not match
+        Object v = serviceBundle.getHeaders().get( Constants.BUNDLE_VERSION );
+        Version s = ( v == null ) ? Version.emptyVersion : new Version( v.toString() );
+        if ( !this.version.equals( s.toString() ) )
         {
             return false;
         }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java b/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java
index 98c7635..eaa0f3b 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java
@@ -52,7 +52,6 @@
 
     public Enumeration findEntries( String arg0, String arg1, boolean arg2 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
@@ -71,35 +70,30 @@
 
     public URL getEntry( String arg0 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public Enumeration getEntryPaths( String arg0 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public Dictionary getHeaders()
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public Dictionary getHeaders( String arg0 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public long getLastModified()
     {
-        // TODO Auto-generated method stub
         return 0;
     }
 
@@ -112,141 +106,129 @@
 
     public ServiceReference[] getRegisteredServices()
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public URL getResource( String arg0 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
-    public Enumeration getResources( String arg0 ) throws IOException
+    public Enumeration getResources( String arg0 )
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public ServiceReference[] getServicesInUse()
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public int getState()
     {
-        // TODO Auto-generated method stub
         return 0;
     }
 
 
     public String getSymbolicName()
     {
-        // TODO Auto-generated method stub
         return null;
     }
 
 
     public boolean hasPermission( Object arg0 )
     {
-        // TODO Auto-generated method stub
         return false;
     }
 
 
     public Class loadClass( String arg0 ) throws ClassNotFoundException
     {
-        // TODO Auto-generated method stub
-        return null;
+        throw new ClassNotFoundException( arg0 );
     }
 
 
-    public void start() throws BundleException
+    public void start()
     {
-        // TODO Auto-generated method stub
-
     }
 
 
-    public void stop() throws BundleException
+    public void stop()
     {
-        // TODO Auto-generated method stub
-
     }
 
 
-    public void uninstall() throws BundleException
+    public void uninstall()
     {
-        // TODO Auto-generated method stub
-
     }
 
 
-    public void update() throws BundleException
+    public void update()
     {
-        // TODO Auto-generated method stub
-
     }
 
 
     public void update( InputStream arg0 ) throws BundleException
     {
-        // TODO Auto-generated method stub
-
+        if ( arg0 != null )
+        {
+            try
+            {
+                arg0.close();
+            }
+            catch ( IOException ioe )
+            {
+                throw new BundleException( ioe.getMessage(), ioe );
+            }
+        }
     }
 
 
-    public void start( int options ) throws BundleException
+    public void start( int options )
     {
-        // TODO Auto-generated method stub
-
     }
 
 
-    public void stop( int options ) throws BundleException
+    public void stop( int options )
     {
-        // TODO Auto-generated method stub
-
     }
 
 
     public int compareTo( Bundle o )
     {
-        // TODO Auto-generated method stub
         return 0;
     }
 
 
+    // Framework 1.5 additions
+
     public Map<X509Certificate, List<X509Certificate>> getSignerCertificates( int signersType )
     {
-        // TODO Auto-generated method stub
-        return null;
+        throw new AbstractMethodError( "Not supported on Framework API 1.4; added in Framework API 1.5" );
     }
 
 
     public Version getVersion()
     {
-        // TODO Auto-generated method stub
-        return null;
+        throw new AbstractMethodError( "Not supported on Framework API 1.4; added in Framework API 1.5" );
     }
 
 
+    // Framework 1.6 additions
+
     public <A> A adapt( Class<A> type )
     {
-        // TODO Auto-generated method stub
-        return null;
+        throw new AbstractMethodError( "Not supported on Framework API 1.4; added in Framework API 1.6" );
     }
 
 
     public File getDataFile( String filename )
     {
-        // TODO Auto-generated method stub
-        return null;
+        throw new AbstractMethodError( "Not supported on Framework API 1.4; added in Framework API 1.6" );
     }
 
 }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/MockServiceReference.java b/configadmin/src/test/java/org/apache/felix/cm/MockServiceReference.java
new file mode 100644
index 0000000..fa58358
--- /dev/null
+++ b/configadmin/src/test/java/org/apache/felix/cm/MockServiceReference.java
@@ -0,0 +1,64 @@
+/*
+ * 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.cm;
+
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+
+public class MockServiceReference implements ServiceReference
+{
+
+    public Object getProperty( String key )
+    {
+        return null;
+    }
+
+
+    public String[] getPropertyKeys()
+    {
+        return null;
+    }
+
+
+    public Bundle getBundle()
+    {
+        return null;
+    }
+
+
+    public Bundle[] getUsingBundles()
+    {
+        return null;
+    }
+
+
+    public boolean isAssignableTo( Bundle bundle, String className )
+    {
+        return false;
+    }
+
+
+    public int compareTo( Object reference )
+    {
+        return 0;
+    }
+
+}
diff --git a/configadmin/src/test/java/org/apache/felix/cm/impl/helper/TargetedPidTest.java b/configadmin/src/test/java/org/apache/felix/cm/impl/helper/TargetedPidTest.java
index 6e7aa46..3f7a6da 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/impl/helper/TargetedPidTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/impl/helper/TargetedPidTest.java
@@ -19,7 +19,20 @@
 package org.apache.felix.cm.impl.helper;
 
 
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.cm.MockBundle;
+import org.apache.felix.cm.MockBundleContext;
+import org.apache.felix.cm.MockServiceReference;
 import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 
 
 public class TargetedPidTest
@@ -28,13 +41,171 @@
     @Test
     public void test_matchLevel()
     {
-//        TestCase.fail( "not implemented" );
+        //        TestCase.fail( "not implemented" );
     }
 
 
     @Test
     public void test_equals()
     {
-//        TestCase.fail( "not implemented" );
+        //        TestCase.fail( "not implemented" );
     }
-}
+
+
+    @Test
+    public void test_matchesTarget_no_target()
+    {
+        final String pid = "a.b.c";
+        final String symbolicName = "b1";
+        final Version version = new Version( "1.0.0" );
+        final String location = "loc:" + symbolicName;
+
+        final Bundle b1 = createBundle( symbolicName, version, location );
+        final ServiceReference r1 = createServiceReference( b1, pid );
+
+        final ServiceReference rn = createServiceReference( createBundle( symbolicName + "_", version, location ), pid );
+        final ServiceReference rv = createServiceReference(
+            createBundle( symbolicName, new Version( "0.2.0" ), location ), pid );
+        final ServiceReference rl = createServiceReference( createBundle( symbolicName, version, location + "_" ), pid );
+        final ServiceReference rnone = createServiceReference( null, pid );
+
+        final TargetedPID p1 = new TargetedPID( String.format( "%s", pid ) );
+
+        TestCase.assertTrue( p1.matchesTarget( r1 ) );
+        TestCase.assertTrue( p1.matchesTarget( rn ) );
+        TestCase.assertTrue( p1.matchesTarget( rv ) );
+        TestCase.assertTrue( p1.matchesTarget( rl ) );
+        TestCase.assertFalse( "Unregistered service must not match targeted PID",  p1.matchesTarget( rnone ) );
+    }
+
+
+    @Test
+    public void test_matchesTarget_name()
+    {
+        final String pid = "a.b.c";
+        final String symbolicName = "b1";
+        final Version version = new Version( "1.0.0" );
+        final String location = "loc:" + symbolicName;
+
+        final Bundle b1 = createBundle( symbolicName, version, location );
+        final ServiceReference r1 = createServiceReference( b1, pid );
+
+        final ServiceReference rn = createServiceReference( createBundle( symbolicName + "_", version, location ), pid );
+        final ServiceReference rv = createServiceReference(
+            createBundle( symbolicName, new Version( "0.2.0" ), location ), pid );
+        final ServiceReference rl = createServiceReference( createBundle( symbolicName, version, location + "_" ), pid );
+        final ServiceReference rnone = createServiceReference( null, pid );
+
+        final TargetedPID p1 = new TargetedPID( String.format( "%s|%s", pid, symbolicName ) );
+
+        TestCase.assertTrue( "Reference from same bundle must match targeted PID",  p1.matchesTarget( r1 ) );
+        TestCase.assertFalse( "Different symbolic name must not match targeted PID",  p1.matchesTarget( rn ) );
+        TestCase.assertTrue( p1.matchesTarget( rv ) );
+        TestCase.assertTrue( p1.matchesTarget( rl ) );
+        TestCase.assertFalse( "Unregistered service must not match targeted PID",  p1.matchesTarget( rnone ) );
+    }
+
+
+    @Test
+    public void test_matchesTarget_name_version()
+    {
+        final String pid = "a.b.c";
+        final String symbolicName = "b1";
+        final Version version = new Version( "1.0.0" );
+        final String location = "loc:" + symbolicName;
+
+        final Bundle b1 = createBundle( symbolicName, version, location );
+        final ServiceReference r1 = createServiceReference( b1, pid );
+
+        final ServiceReference rn = createServiceReference( createBundle( symbolicName + "_", version, location ), pid );
+        final ServiceReference rv = createServiceReference(
+            createBundle( symbolicName, new Version( "0.2.0" ), location ), pid );
+        final ServiceReference rl = createServiceReference( createBundle( symbolicName, version, location + "_" ), pid );
+        final ServiceReference rnone = createServiceReference( null, pid );
+
+        final TargetedPID p1 = new TargetedPID( String.format( "%s|%s|%s", pid, symbolicName, version ) );
+
+        TestCase.assertTrue( "Reference from same bundle must match targeted PID",  p1.matchesTarget( r1 ) );
+        TestCase.assertFalse( "Different symbolic name must not match targeted PID",  p1.matchesTarget( rn ) );
+        TestCase.assertFalse( "Different version must not match targeted PID",  p1.matchesTarget( rv ) );
+        TestCase.assertTrue( p1.matchesTarget( rl ) );
+        TestCase.assertFalse( "Unregistered service must not match targeted PID",  p1.matchesTarget( rnone ) );
+    }
+
+
+
+    @Test
+    public void test_matchesTarget_name_version_location()
+    {
+        final String pid = "a.b.c";
+        final String symbolicName = "b1";
+        final Version version = new Version( "1.0.0" );
+        final String location = "loc:" + symbolicName;
+
+        final Bundle b1 = createBundle( symbolicName, version, location );
+        final ServiceReference r1 = createServiceReference( b1, pid );
+
+        final ServiceReference rn = createServiceReference( createBundle( symbolicName + "_", version, location ), pid );
+        final ServiceReference rv = createServiceReference(
+            createBundle( symbolicName, new Version( "0.2.0" ), location ), pid );
+        final ServiceReference rl = createServiceReference( createBundle( symbolicName, version, location + "_" ), pid );
+        final ServiceReference rnone = createServiceReference( null, pid );
+
+        final TargetedPID p1 = new TargetedPID( String.format( "%s|%s|%s|%s", pid, symbolicName, version, location ) );
+
+        TestCase.assertTrue( "Reference from same bundle must match targeted PID",  p1.matchesTarget( r1 ) );
+        TestCase.assertFalse( "Different symbolic name must not match targeted PID",  p1.matchesTarget( rn ) );
+        TestCase.assertFalse( "Different version must not match targeted PID",  p1.matchesTarget( rv ) );
+        TestCase.assertFalse( "Different location must not match targeted PID",  p1.matchesTarget( rl ) );
+        TestCase.assertFalse( "Unregistered service must not match targeted PID",  p1.matchesTarget( rnone ) );
+    }
+
+
+    Bundle createBundle( final String symbolicName, final Version version, final String location )
+    {
+        BundleContext ctx = new MockBundleContext();
+        return new MockBundle( ctx, location )
+        {
+            public String getSymbolicName()
+            {
+                return symbolicName;
+            }
+
+
+            @Override
+            public Dictionary getHeaders()
+            {
+                return new Hashtable<String, Object>()
+                {
+                    {
+                        put( Constants.BUNDLE_VERSION, version.toString() );
+                    }
+                };
+            }
+        };
+    }
+
+
+    ServiceReference<?> createServiceReference( final Bundle bundle, final Object pids )
+    {
+        return new MockServiceReference()
+        {
+            @Override
+            public Bundle getBundle()
+            {
+                return bundle;
+            }
+
+
+            @Override
+            public Object getProperty( String key )
+            {
+                if ( Constants.SERVICE_PID.equals( key ) )
+                {
+                    return pids;
+                }
+                return super.getProperty( key );
+            }
+        };
+    }
+}
\ No newline at end of file