FELIX-3577 Adapt to new helper classes and add dependency to OSGi Core 5.0 (to
  have support for generics). In turn we limit the Framework API import to 1.4
  (aka R4.1) to still be able to support older framework releases (the integration
  tests run with Felix Framework 1.8.0). This also allows me to remove the copy
  of the generified OSGi ServiceReference class.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1356236 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/pom.xml b/configadmin/pom.xml
index b6b0bf3..4d5e84c 100644
--- a/configadmin/pom.xml
+++ b/configadmin/pom.xml
@@ -81,10 +81,15 @@
     </properties>
 
     <dependencies>
+    
+        <!--
+            Depend on latest version to make use of generics. Still we
+            make sure to only require Framework API 1.5 (OSGi Core R4.2)
+        -->
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>4.1.0</version>
+            <version>5.0.0</version>
             <scope>provided</scope>
         </dependency>
         
@@ -168,10 +173,12 @@
                         </Export-Package>
                         <Private-Package>
                             org.apache.felix.cm.impl,
+                            org.apache.felix.cm.impl.helper,
                             org.osgi.util.tracker
                         </Private-Package>
                         <Import-Package>
                             org.osgi.service.cm;version="[1.5,1.6)",
+                            org.osgi.framework;version="[1.4,2)",
                             *
                         </Import-Package>
                         <DynamicImport-Package>
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java b/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
index b4076c7..214ca25 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
@@ -37,7 +37,7 @@
  * out by the Configuration Admin Service Specification requiring the property
  * names to keep case but to ignore case when accessing the properties.
  */
-class CaseInsensitiveDictionary extends Dictionary
+public class CaseInsensitiveDictionary extends Dictionary
 {
 
     /**
@@ -52,14 +52,14 @@
     private Hashtable originalKeys;
 
 
-    CaseInsensitiveDictionary()
+    public CaseInsensitiveDictionary()
     {
         internalMap = new Hashtable();
         originalKeys = new Hashtable();
     }
 
 
-    CaseInsensitiveDictionary( Dictionary props )
+    public CaseInsensitiveDictionary( Dictionary props )
     {
         this();
 
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
index 7d58aad..90aaf25 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationImpl.java
@@ -37,7 +37,7 @@
  * the {@link ConfigurationAdapter} class, whose instances are actually returned
  * to clients.
  */
-class ConfigurationImpl extends ConfigurationBase
+public class ConfigurationImpl extends ConfigurationBase
 {
 
     /*
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
index bd9d01d..10e26a2 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/ConfigurationManager.java
@@ -22,12 +22,42 @@
 import java.io.IOException;
 import java.security.SecureRandom;
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
 
 import org.apache.felix.cm.PersistenceManager;
 import org.apache.felix.cm.file.FilePersistenceManager;
-import org.osgi.framework.*;
-import org.osgi.service.cm.*;
+import org.apache.felix.cm.impl.helper.BaseTracker;
+import org.apache.felix.cm.impl.helper.ManagedServiceFactoryTracker;
+import org.apache.felix.cm.impl.helper.ManagedServiceTracker;
+import org.apache.felix.cm.impl.helper.TargetedPID;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+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;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.cm.ConfigurationPermission;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.cm.SynchronousConfigurationListener;
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
@@ -97,7 +127,7 @@
     private static Random numberGenerator;
 
     // the BundleContext of the Configuration Admin Service bundle
-    private BundleContext bundleContext;
+    BundleContext bundleContext;
 
     // the service registration of the configuration admin
     private volatile ServiceRegistration configurationAdminRegistration;
@@ -109,10 +139,10 @@
     private ServiceTracker configurationListenerTracker;
 
     // service tracker for managed services
-    private ServiceTracker managedServiceTracker;
+    private ManagedServiceTracker managedServiceTracker;
 
     // service tracker for managed service factories
-    private ServiceTracker managedServiceFactoryTracker;
+    private ManagedServiceFactoryTracker managedServiceFactoryTracker;
 
     // PersistenceManager services
     private ServiceTracker persistenceManagerTracker;
@@ -332,6 +362,10 @@
         return isActive;
     }
 
+    public BundleContext getBundleContext()
+    {
+        return bundleContext;
+    }
 
     // ---------- Configuration caching support --------------------------------
 
@@ -759,50 +793,26 @@
      * service property as a String[], which may be <code>null</code> if
      * the ManagedService does not have such a property.
      */
-    private void configure( String[] pids, ServiceReference sr, ManagedService service )
-    {
-        if ( pids != null )
-        {
-            if ( isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                log( LogService.LOG_DEBUG, "configure(ManagedService {0})", new Object[]
-                    { toString( sr ) } );
-            }
-
-            for ( int i = 0; i < pids.length; i++ )
-            {
-                ManagedServiceUpdate update = new ManagedServiceUpdate( pids[i], sr, service );
-                updateThread.schedule( update );
-                log( LogService.LOG_DEBUG, "ManagedServiceUpdate({0}) scheduled", new Object[]
-                    { pids[i] } );
-            }
-        }
-    }
-
-
     /**
      * Configures the ManagedServiceFactory and returns the service.pid
      * service property as a String[], which may be <code>null</code> if
      * the ManagedServiceFactory does not have such a property.
      */
-    private void configure( String[] pids, ServiceReference sr, ManagedServiceFactory service )
+    //TODO: replace above configure methods
+    public void configure( String pid, ServiceReference sr, Object service, final boolean factory )
     {
-        if ( pids != null )
+        Runnable r;
+        if ( factory )
         {
-            if ( isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                log( LogService.LOG_DEBUG, "configure(ManagedServiceFactory {0})", new Object[]
-                    { toString( sr ) } );
-            }
-
-            for ( int i = 0; i < pids.length; i++ )
-            {
-                ManagedServiceFactoryUpdate update = new ManagedServiceFactoryUpdate( pids[i], sr, service );
-                updateThread.schedule( update );
-                log( LogService.LOG_DEBUG, "ManagedServiceFactoryUpdate({0}) scheduled", new Object[]
-                    { pids[i] } );
-            }
+            r = new ManagedServiceFactoryUpdate( pid, sr, ( ManagedServiceFactory ) service );
         }
+        else
+        {
+            r = new ManagedServiceUpdate( pid, sr, ( ManagedService ) service );
+        }
+        updateThread.schedule( r );
+        log( LogService.LOG_DEBUG, "[{0}] scheduled", new Object[]
+            { r } );
     }
 
 
@@ -884,7 +894,7 @@
      * @param cfg The configuration object whose properties have to be passed
      *          through the plugins
      */
-    private void callPlugins( final Dictionary props, final String targetPid, final ServiceReference sr,
+    public void callPlugins( final Dictionary props, final String targetPid, final ServiceReference sr,
         final ConfigurationImpl cfg )
     {
         // guard against NPE for new configuration never updated
@@ -995,13 +1005,13 @@
     }
 
 
-    boolean isLogEnabled( int level )
+    public boolean isLogEnabled( int level )
     {
         return level <= logLevel;
     }
 
 
-    void log( int level, String format, Object[] args )
+    public void log( int level, String format, Object[] args )
     {
         if ( isLogEnabled( level ) )
         {
@@ -1022,7 +1032,7 @@
     }
 
 
-    void log( int level, String message, Throwable t )
+    public void log( int level, String message, Throwable t )
     {
         // log using the LogService if available
         Object log = logTracker.getService();
@@ -1064,47 +1074,9 @@
     }
 
 
-    /**
-     * Returns the <code>service.pid</code> property of the service reference as
-     * an array of strings or <code>null</code> if the service reference does
-     * not have a service PID property.
-     * <p>
-     * The service.pid property may be a single string, in which case a single
-     * element array is returned. If the property is an array of string, this
-     * array is returned. If the property is a collection it is assumed to be a
-     * collection of strings and the collection is converted to an array to be
-     * returned. Otherwise (also if the property is not set) <code>null</code>
-     * is returned.
-     *
-     * @throws NullPointerException
-     *             if reference is <code>null</code>
-     * @throws ArrayStoreException
-     *             if the service pid is a collection and not all elements are
-     *             strings.
-     */
-    static String[] getServicePid( ServiceReference reference )
-    {
-        Object pidObj = reference.getProperty( Constants.SERVICE_PID );
-        if ( pidObj instanceof String )
-        {
-            return new String[]
-                { ( String ) pidObj };
-        }
-        else if ( pidObj instanceof String[] )
-        {
-            return ( String[] ) pidObj;
-        }
-        else if ( pidObj instanceof Collection )
-        {
-            Collection pidCollection = ( Collection ) pidObj;
-            return ( String[] ) pidCollection.toArray( new String[pidCollection.size()] );
-        }
-
-        return null;
-    }
 
 
-    static String toString( ServiceReference ref )
+    public static String toString( ServiceReference ref )
     {
         String[] ocs = ( String[] ) ref.getProperty( "objectClass" );
         StringBuffer buf = new StringBuffer("[");
@@ -1133,7 +1105,7 @@
     }
 
 
-    void handleCallBackError( final Throwable error, final ServiceReference target, final ConfigurationImpl config )
+    public void handleCallBackError( final Throwable error, final ServiceReference target, final ConfigurationImpl config )
     {
         if ( error instanceof ConfigurationException )
         {
@@ -1216,178 +1188,6 @@
 
     // ---------- inner classes
 
-    private ServiceHelper createServiceHelper( ConfigurationImpl config )
-    {
-        if ( config.getFactoryPid() == null )
-        {
-            return new ManagedServiceHelper( config );
-        }
-        return new ManagedServiceFactoryHelper( config );
-    }
-
-    private abstract class ServiceHelper
-    {
-        protected final ConfigurationImpl config;
-
-        private final Dictionary properties;
-
-        protected ServiceHelper( ConfigurationImpl config )
-        {
-            this.config = config;
-            this.properties = config.getProperties( true );
-        }
-
-        final ServiceReference[] getServices( )
-        {
-            try
-            {
-                ServiceReference[] refs = doGetServices();
-                if ( refs != null && refs.length > 1 )
-                {
-                    Arrays.sort( refs, RankingComparator.SRV_RANKING );
-                }
-                return refs;
-            }
-            catch ( InvalidSyntaxException ise )
-            {
-                log( LogService.LOG_ERROR, "Service selection filter is invalid to update {0}", new Object[]
-                    { config, ise } );
-            }
-            return null;
-        }
-
-
-        protected abstract ServiceReference[] doGetServices() throws InvalidSyntaxException;
-
-
-        abstract void provide( ServiceReference service );
-
-
-        abstract void remove( ServiceReference service );
-
-
-        protected Dictionary getProperties( String targetPid, ServiceReference service )
-        {
-            Dictionary props = new CaseInsensitiveDictionary( this.properties );
-            callPlugins( props, targetPid, service, config );
-            return props;
-        }
-    }
-
-    private class ManagedServiceHelper extends ServiceHelper
-    {
-
-        protected ManagedServiceHelper( ConfigurationImpl config )
-        {
-            super( config );
-        }
-
-
-        public ServiceReference[] doGetServices() throws InvalidSyntaxException
-        {
-            return bundleContext.getServiceReferences( ManagedService.class.getName(), "(" + Constants.SERVICE_PID
-                + "=" + config.getPid() + ")" );
-        }
-
-
-        public void provide( ServiceReference service )
-        {
-            ManagedService srv = ( ManagedService ) bundleContext.getService( service );
-            if ( srv != null )
-            {
-                try
-                {
-                    Dictionary props = getProperties( this.config.getPid(), service );
-                    srv.updated( props );
-                }
-                catch ( Throwable t )
-                {
-                    handleCallBackError( t, service, config );
-                }
-                finally
-                {
-                    bundleContext.ungetService( service );
-                }
-            }
-        }
-
-
-        public void remove( ServiceReference service )
-        {
-            ManagedService srv = ( ManagedService ) bundleContext.getService( service );
-            try
-            {
-                srv.updated( null );
-            }
-            catch ( Throwable t )
-            {
-                handleCallBackError( t, service, config );
-            }
-            finally
-            {
-                bundleContext.ungetService( service );
-            }
-        }
-
-    }
-
-    private class ManagedServiceFactoryHelper extends ServiceHelper
-    {
-
-        protected ManagedServiceFactoryHelper( ConfigurationImpl config )
-        {
-            super( config );
-        }
-
-
-        public ServiceReference[] doGetServices() throws InvalidSyntaxException
-        {
-            return bundleContext.getServiceReferences( ManagedServiceFactory.class.getName(), "("
-                + Constants.SERVICE_PID + "=" + config.getFactoryPid() + ")" );
-        }
-
-
-        public void provide( ServiceReference service )
-        {
-            ManagedServiceFactory srv = ( ManagedServiceFactory ) bundleContext.getService( service );
-            if ( srv != null )
-            {
-                try
-                {
-                    Dictionary props = getProperties( this.config.getFactoryPid(), service );
-                    srv.updated( config.getPid(), props );
-                }
-                catch ( Throwable t )
-                {
-                    handleCallBackError( t, service, config );
-                }
-                finally
-                {
-                    bundleContext.ungetService( service );
-                }
-            }
-        }
-
-
-        public void remove( ServiceReference service )
-        {
-            ManagedServiceFactory srv = ( ManagedServiceFactory ) bundleContext.getService( service );
-            try
-            {
-                srv.deleted( config.getPid() );
-            }
-            catch ( Throwable t )
-            {
-                handleCallBackError( t, service, config );
-            }
-            finally
-            {
-                bundleContext.ungetService( service );
-            }
-        }
-
-    }
-
     /**
      * The <code>ManagedServiceUpdate</code> updates a freshly registered
      * <code>ManagedService</code> with a specific configuration. If a
@@ -1687,6 +1487,32 @@
         }
     }
 
+    private abstract class ConfigurationProvider<T> implements Runnable {
+
+        protected final ConfigurationImpl config;
+        protected final long revision;
+        protected final Dictionary<String, ?> properties;
+        protected final BaseTracker<T> helper;
+
+        protected ConfigurationProvider(final ConfigurationImpl config) {
+            this.config = config;
+            this.helper = ( BaseTracker<T> ) ( ( config.getFactoryPid() == null ) ? managedServiceTracker : managedServiceFactoryTracker );
+            synchronized ( config )
+            {
+                this.revision = config.getRevision();
+                this.properties = config.getProperties( true );
+            }
+        }
+
+        protected TargetedPID getTargetedServicePid() {
+            final String factoryPid = this.config.getFactoryPid();
+            if (factoryPid == null) {
+                return new TargetedPID( this.config.getPid() );
+            }
+            return new TargetedPID( factoryPid );
+        }
+
+    }
 
     /**
      * The <code>UpdateConfiguration</code> is used to update
@@ -1694,22 +1520,12 @@
      * they are subscribed to. This may cause the configuration to be
      * supplied to multiple services.
      */
-    private class UpdateConfiguration implements Runnable
+    private class UpdateConfiguration extends ConfigurationProvider
     {
 
-        private final ConfigurationImpl config;
-        private final ServiceHelper helper;
-        private final long revision;
-
-
         UpdateConfiguration( final ConfigurationImpl config )
         {
-            this.config = config;
-            synchronized ( config )
-            {
-                this.helper = createServiceHelper( config );
-                this.revision = config.getRevision();
-            }
+            super( config );
         }
 
 
@@ -1718,19 +1534,18 @@
             log( LogService.LOG_DEBUG, "Updating configuration {0} to revision #{1}", new Object[]
                 { config.getPid(), new Long( revision ) } );
 
-            final ServiceReference[] srList = helper.getServices();
-            if ( srList != null )
+            final List<ServiceReference<?>> srList = this.helper.getServices( getTargetedServicePid() );
+            if ( !srList.isEmpty() )
             {
                 // optionally bind dynamically to the first service
-                config.tryBindLocation( srList[0].getBundle().getLocation() );
+                config.tryBindLocation( srList.get( 0 ).getBundle().getLocation() );
 
                 final String configBundleLocation = config.getBundleLocation();
 
                 // provide configuration to all services from the
                 // correct bundle
-                for ( int i = 0; i < srList.length; i++ )
+                for (ServiceReference<?> ref : srList)
                 {
-                    final ServiceReference ref = srList[i];
                     final Bundle refBundle = ref.getBundle();
                     if ( refBundle == null )
                     {
@@ -1741,7 +1556,7 @@
                     }
                     else if ( canReceive( refBundle, configBundleLocation ) )
                     {
-                        helper.provide( ref );
+                        helper.provide( ref, this.config, this.properties );
                     }
                     else
                     {
@@ -1775,10 +1590,9 @@
      * <code>ManagedService[Factory]</code> services of a configuration
      * being deleted.
      */
-    private class DeleteConfiguration implements Runnable
+    private class DeleteConfiguration extends ConfigurationProvider
     {
 
-        private final ConfigurationImpl config;
         private final String configLocation;
 
 
@@ -1789,7 +1603,7 @@
              * after calling this method. The pid and factoryPid fields are
              * final and cannot be reset.
              */
-            this.config = config;
+            super(config);
             this.configLocation = config.getBundleLocation();
         }
 
@@ -1798,14 +1612,12 @@
         {
             final String pid = config.getPid();
             final String factoryPid = config.getFactoryPid();
-            final ServiceHelper helper = createServiceHelper( config );
 
-            ServiceReference[] srList = helper.getServices( );
-            if ( srList != null )
+            List<ServiceReference<?>> srList = this.helper.getServices( getTargetedServicePid() );
+            if ( !srList.isEmpty() )
             {
-                for ( int i = 0; i < srList.length; i++ )
+                for (ServiceReference<?> sr : srList)
                 {
-                    final ServiceReference sr = srList[i];
                     final Bundle srBundle = sr.getBundle();
                     if ( srBundle == null )
                     {
@@ -1816,7 +1628,7 @@
                     }
                     else if ( canReceive( srBundle, configLocation ) )
                     {
-                        helper.remove( sr );
+                        this.helper.remove( sr, this.config );
                     }
                     else
                     {
@@ -1852,29 +1664,25 @@
         }
     }
 
-    private class LocationChanged implements Runnable
+    private class LocationChanged extends ConfigurationProvider
     {
-        private final ConfigurationImpl config;
         private final String oldLocation;
 
 
         LocationChanged( ConfigurationImpl config, String oldLocation )
         {
-            this.config = config;
+            super( config );
             this.oldLocation = oldLocation;
         }
 
 
         public void run()
         {
-            ServiceHelper helper = createServiceHelper( this.config );
-            ServiceReference[] srList = helper.getServices( );
-            if ( srList != null )
+            List<ServiceReference<?>> srList = helper.getServices( getTargetedServicePid() );
+            if ( !srList.isEmpty() )
             {
-                for ( int i = 0; i < srList.length; i++ )
+                for (final ServiceReference<?> sr : srList)
                 {
-                    final ServiceReference sr = srList[i];
-
                     final Bundle srBundle = sr.getBundle();
                     if ( srBundle == null )
                     {
@@ -1905,7 +1713,7 @@
                     else if ( !wasVisible && isVisible )
                     {
                         // call updated method
-                        helper.provide( sr );
+                        helper.provide( sr, this.config, this.properties );
                         log( LogService.LOG_DEBUG, "Configuration {0} provided to {1} (new visibility)", new Object[]
                             { config.getPid(), ConfigurationManager.toString( sr ) } );
                     }
@@ -2055,169 +1863,4 @@
             }
         }
     }
-
-    private static class ManagedServiceTracker extends ServiceTracker
-    {
-
-        private final ConfigurationManager cm;
-
-
-        ManagedServiceTracker( ConfigurationManager cm )
-        {
-            super( cm.bundleContext, ManagedService.class.getName(), null );
-            this.cm = cm;
-            open();
-        }
-
-
-        public Object addingService( ServiceReference reference )
-        {
-            Object service = super.addingService( reference );
-
-            // configure the managed service
-            final String[] pids;
-            if ( service instanceof ManagedService )
-            {
-                pids = getServicePid( reference );
-                cm.configure( pids, reference, ( ManagedService ) service );
-            }
-            else
-            {
-                cm.log( LogService.LOG_WARNING, "Service {0} is not a ManagedService", new Object[]
-                    { service } );
-                pids = null;
-            }
-
-            return new ManagedServiceHolder( service, pids );
-        }
-
-
-        public void modifiedService( ServiceReference reference, Object service )
-        {
-            ManagedServiceHolder holder = ( ManagedServiceHolder ) service;
-            String[] pids = getServicePid( reference );
-
-            if ( holder.isDifferentPids( pids ) )
-            {
-                cm.configure( pids, reference, ( ManagedService ) holder.getManagedService() );
-                holder.setConfiguredPids( pids );
-            }
-        }
-
-
-        public void removedService( ServiceReference reference, Object service )
-        {
-            final Object serviceObject = ( ( ManagedServiceHolder ) service ).getManagedService();
-            super.removedService( reference, serviceObject );
-        }
-    }
-
-    private static class ManagedServiceFactoryTracker extends ServiceTracker
-    {
-        private final ConfigurationManager cm;
-
-
-        ManagedServiceFactoryTracker( ConfigurationManager cm )
-        {
-            super( cm.bundleContext, ManagedServiceFactory.class.getName(), null );
-            this.cm = cm;
-            open();
-        }
-
-
-        public Object addingService( ServiceReference reference )
-        {
-            Object serviceObject = super.addingService( reference );
-
-            // configure the managed service factory
-            final String[] pids;
-            if ( serviceObject instanceof ManagedServiceFactory )
-            {
-                pids = getServicePid( reference );
-                cm.configure( pids, reference, ( ManagedServiceFactory ) serviceObject );
-            }
-            else
-            {
-                cm.log( LogService.LOG_WARNING, "Service {0} is not a ManagedServiceFactory", new Object[]
-                    { serviceObject } );
-                pids = null;
-            }
-
-            return new ManagedServiceHolder( serviceObject, pids );
-        }
-
-
-        public void modifiedService( ServiceReference reference, Object service )
-        {
-            ManagedServiceHolder holder = ( ManagedServiceHolder ) service;
-            String[] pids = getServicePid( reference );
-
-            if ( holder.isDifferentPids( pids ) )
-            {
-                cm.configure( pids, reference, ( ManagedServiceFactory ) holder.getManagedService() );
-                holder.setConfiguredPids( pids );
-            }
-
-            super.modifiedService( reference, service );
-        }
-
-
-        public void removedService( ServiceReference reference, Object service )
-        {
-            final Object serviceObject = ( ( ManagedServiceHolder ) service ).getManagedService();
-            super.removedService( reference, serviceObject );
-        }
-    }
-
-    private static class ManagedServiceHolder
-    {
-        private final Object managedService;
-        private String[] configuredPids;
-
-
-        ManagedServiceHolder( final Object managedService, final String[] configuredPids )
-        {
-            this.managedService = managedService;
-            this.configuredPids = configuredPids;
-        }
-
-
-        public Object getManagedService()
-        {
-            return managedService;
-        }
-
-
-        public void setConfiguredPids( String[] configuredPids )
-        {
-            this.configuredPids = configuredPids;
-        }
-
-
-        boolean isDifferentPids( final String[] pids )
-        {
-            if ( this.configuredPids == null && pids == null )
-            {
-                return false;
-            }
-            else if ( this.configuredPids == null )
-            {
-                return true;
-            }
-            else if ( pids == null )
-            {
-                return true;
-            }
-            else if ( this.configuredPids.length != pids.length )
-            {
-                return true;
-            }
-            else
-            {
-                HashSet thisPids = new HashSet( Arrays.asList( this.configuredPids ) );
-                HashSet otherPids = new HashSet( Arrays.asList( pids ) );
-                return !thisPids.equals( otherPids );
-            }
-        }
-    }
 }
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java b/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java
index e4e763f..627e544 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/RankingComparator.java
@@ -32,7 +32,7 @@
  * array is the one to use first and the last elementis the one to
  * use last.
  */
-abstract class RankingComparator implements Comparator
+public abstract class RankingComparator implements Comparator
 {
 
     /**
@@ -47,7 +47,7 @@
      * <li><code>&gt; 0</code> if obj1 has lower ranking than obj2</li>
      * </ul>
      */
-    static Comparator SRV_RANKING = new RankingComparator()
+    public static Comparator SRV_RANKING = new RankingComparator()
     {
         public int compare( Object obj1, Object obj2 )
         {
@@ -87,7 +87,7 @@
      * <li><code>&gt; 0</code> if obj1 has higher ranking than obj2</li>
      * </ul>
      */
-    static Comparator CM_RANKING = new RankingComparator()
+    public static Comparator CM_RANKING = new RankingComparator()
     {
         public int compare( Object obj1, Object obj2 )
         {
diff --git a/configadmin/src/main/java/org/osgi/framework/ServiceReference.java b/configadmin/src/main/java/org/osgi/framework/ServiceReference.java
deleted file mode 100644
index 156e30b..0000000
--- a/configadmin/src/main/java/org/osgi/framework/ServiceReference.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceReference.java,v 1.20 2007/02/21 16:49:05 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2000, 2007). All Rights Reserved.
- *
- * Licensed 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.osgi.framework;
-
-/**
- * A reference to a service.
- *
- * <p>
- * The Framework returns <code>ServiceReference</code> objects from the
- * <code>BundleContext.getServiceReference</code> and
- * <code>BundleContext.getServiceReferences</code> methods.
- * <p>
- * A <code>ServiceReference</code> object may be shared between bundles and
- * can be used to examine the properties of the service and to get the service
- * object.
- * <p>
- * Every service registered in the Framework has a unique
- * <code>ServiceRegistration</code> object and may have multiple, distinct
- * <code>ServiceReference</code> objects referring to it.
- * <code>ServiceReference</code> objects associated with a
- * <code>ServiceRegistration</code> object have the same <code>hashCode</code>
- * and are considered equal (more specifically, their <code>equals()</code>
- * method will return <code>true</code> when compared).
- * <p>
- * If the same service object is registered multiple times,
- * <code>ServiceReference</code> objects associated with different
- * <code>ServiceRegistration</code> objects are not equal.
- *
- * @see BundleContext#getServiceReference
- * @see BundleContext#getServiceReferences
- * @see BundleContext#getService
- * @ThreadSafe
- * @version $Revision: 1.20 $
- */
-
-public interface ServiceReference<T> extends Comparable {
-    /**
-     * Returns the property value to which the specified property key is mapped
-     * in the properties <code>Dictionary</code> object of the service
-     * referenced by this <code>ServiceReference</code> object.
-     *
-     * <p>
-     * Property keys are case-insensitive.
-     *
-     * <p>
-     * This method must continue to return property values after the service has
-     * been unregistered. This is so references to unregistered services (for
-     * example, <code>ServiceReference</code> objects stored in the log) can
-     * still be interrogated.
-     *
-     * @param key The property key.
-     * @return The property value to which the key is mapped; <code>null</code>
-     *         if there is no property named after the key.
-     */
-    public Object getProperty(String key);
-
-    /**
-     * Returns an array of the keys in the properties <code>Dictionary</code>
-     * object of the service referenced by this <code>ServiceReference</code>
-     * object.
-     *
-     * <p>
-     * This method will continue to return the keys after the service has been
-     * unregistered. This is so references to unregistered services (for
-     * example, <code>ServiceReference</code> objects stored in the log) can
-     * still be interrogated.
-     *
-     * <p>
-     * This method is <i>case-preserving </i>; this means that every key in the
-     * returned array must have the same case as the corresponding key in the
-     * properties <code>Dictionary</code> that was passed to the
-     * {@link BundleContext#registerService(String[],Object,java.util.Dictionary)}
-     * or {@link ServiceRegistration#setProperties} methods.
-     *
-     * @return An array of property keys.
-     */
-    public String[] getPropertyKeys();
-
-    /**
-     * Returns the bundle that registered the service referenced by this
-     * <code>ServiceReference</code> object.
-     *
-     * <p>
-     * This method must return <code>null</code> when the service has been
-     * unregistered. This can be used to determine if the service has been
-     * unregistered.
-     *
-     * @return The bundle that registered the service referenced by this
-     *         <code>ServiceReference</code> object; <code>null</code> if
-     *         that service has already been unregistered.
-     * @see BundleContext#registerService(String[],Object,java.util.Dictionary)
-     */
-    public Bundle getBundle();
-
-    /**
-     * Returns the bundles that are using the service referenced by this
-     * <code>ServiceReference</code> object. Specifically, this method returns
-     * the bundles whose usage count for that service is greater than zero.
-     *
-     * @return An array of bundles whose usage count for the service referenced
-     *         by this <code>ServiceReference</code> object is greater than
-     *         zero; <code>null</code> if no bundles are currently using that
-     *         service.
-     *
-     * @since 1.1
-     */
-    public Bundle[] getUsingBundles();
-
-    /**
-     * Tests if the bundle that registered the service referenced by this
-     * <code>ServiceReference</code> and the specified bundle use the same
-     * source for the package of the specified class name.
-     * <p>
-     * This method performs the following checks:
-     * <ol>
-     * <li>Get the package name from the specified class name.</li>
-     * <li>For the bundle that registered the service referenced by this
-     * <code>ServiceReference</code> (registrant bundle); find the source for
-     * the package. If no source is found then return <code>true</code> if the
-     * registrant bundle is equal to the specified bundle; otherwise return
-     * <code>false</code>.</li>
-     * <li>If the package source of the registrant bundle is equal to the
-     * package source of the specified bundle then return <code>true</code>;
-     * otherwise return <code>false</code>.</li>
-     * </ol>
-     *
-     * @param bundle The <code>Bundle</code> object to check.
-     * @param className The class name to check.
-     * @return <code>true</code> if the bundle which registered the service
-     *         referenced by this <code>ServiceReference</code> and the
-     *         specified bundle use the same source for the package of the
-     *         specified class name. Otherwise <code>false</code> is returned.
-     *
-     * @since 1.3
-     */
-    public boolean isAssignableTo(Bundle bundle, String className);
-
-    /**
-     * Compares this <code>ServiceReference</code> with the specified
-     * <code>ServiceReference</code> for order.
-     *
-     * <p>
-     * If this <code>ServiceReference</code> and the specified
-     * <code>ServiceReference</code> have the same
-     * {@link Constants#SERVICE_ID service id} they are equal. This
-     * <code>ServiceReference</code> is less than the specified
-     * <code>ServiceReference</code> if it has a lower
-     * {@link Constants#SERVICE_RANKING service ranking} and greater if it has a
-     * higher service ranking. Otherwise, if this <code>ServiceReference</code>
-     * and the specified <code>ServiceReference</code> have the same
-     * {@link Constants#SERVICE_RANKING service ranking}, this
-     * <code>ServiceReference</code> is less than the specified
-     * <code>ServiceReference</code> if it has a higher
-     * {@link Constants#SERVICE_ID service id} and greater if it has a lower
-     * service id.
-     *
-     * @param reference The <code>ServiceReference</code> to be compared.
-     * @return Returns a negative integer, zero, or a positive integer if this
-     *         <code>ServiceReference</code> is less than, equal to, or
-     *         greater than the specified <code>ServiceReference</code>.
-     * @since 1.4
-     */
-    public int compareTo(Object reference);
-}
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 6273d90..98c7635 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/MockBundle.java
@@ -19,16 +19,21 @@
 package org.apache.felix.cm;
 
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.cert.X509Certificate;
 import java.util.Dictionary;
 import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 
 
 public class MockBundle implements Bundle
@@ -209,4 +214,39 @@
 
     }
 
+
+    public int compareTo( Bundle o )
+    {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+
+    public Map<X509Certificate, List<X509Certificate>> getSignerCertificates( int signersType )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public Version getVersion()
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public <A> A adapt( Class<A> type )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public File getDataFile( String filename )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/MockBundleContext.java b/configadmin/src/test/java/org/apache/felix/cm/MockBundleContext.java
index 8cb6353..af847b3 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/MockBundleContext.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/MockBundleContext.java
@@ -21,6 +21,7 @@
 
 import java.io.File;
 import java.io.InputStream;
+import java.util.Collection;
 import java.util.Dictionary;
 import java.util.Properties;
 
@@ -184,7 +185,7 @@
      * @seeorg.osgi.framework.BundleContext#getService(org.osgi.framework.
      * ServiceReference)
      */
-    public Object getService( ServiceReference arg0 )
+    public <S> S getService( ServiceReference<S> reference )
     {
         return null;
     }
@@ -239,7 +240,7 @@
      * @see org.osgi.framework.BundleContext#registerService(java.lang.String[],
      * java.lang.Object, java.util.Dictionary)
      */
-    public ServiceRegistration registerService( String[] arg0, Object arg1, Dictionary arg2 )
+    public ServiceRegistration<?> registerService( String[] clazzes, Object service, Dictionary<String, ?> properties )
     {
         return null;
     }
@@ -250,7 +251,7 @@
      * @see org.osgi.framework.BundleContext#registerService(java.lang.String,
      * java.lang.Object, java.util.Dictionary)
      */
-    public ServiceRegistration registerService( String arg0, Object arg1, Dictionary arg2 )
+    public ServiceRegistration<?> registerService( String clazz, Object service, Dictionary<String, ?> properties )
     {
         return null;
     }
@@ -294,8 +295,37 @@
      * @seeorg.osgi.framework.BundleContext#ungetService(org.osgi.framework.
      * ServiceReference)
      */
-    public boolean ungetService( ServiceReference arg0 )
+    public boolean ungetService( ServiceReference<?> reference )
     {
         return false;
     }
+
+
+    public <S> ServiceRegistration<S> registerService( Class<S> clazz, S service, Dictionary<String, ?> properties )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public <S> ServiceReference<S> getServiceReference( Class<S> clazz )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public <S> Collection<ServiceReference<S>> getServiceReferences( Class<S> clazz, String filter )
+        throws InvalidSyntaxException
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    public Bundle getBundle( String location )
+    {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java b/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java
deleted file mode 100644
index 8d0226e..0000000
--- a/configadmin/src/test/java/org/apache/felix/cm/impl/ManagedServiceHolderTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.impl;
-
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-
-import junit.framework.TestCase;
-
-
-public class ManagedServiceHolderTest extends TestCase
-{
-
-    private static final Constructor mshConstructor;
-    private static final Method msh_isDifferentPids;
-
-    static
-    {
-        try
-        {
-            Class clazz = Class.forName( "org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceHolder" );
-            mshConstructor = clazz.getDeclaredConstructor( new Class[]
-                { Object.class, String[].class } );
-            mshConstructor.setAccessible( true );
-            msh_isDifferentPids = clazz.getDeclaredMethod( "isDifferentPids", new Class[]
-                { String[].class } );
-            msh_isDifferentPids.setAccessible( true );
-        }
-        catch ( Throwable t )
-        {
-            throw new RuntimeException( t );
-        }
-    }
-
-
-    public void test_isDifferentPids_null_null()
-    {
-        Object holder = createHolder( null );
-        assertFalse( "Expect both pids null to be the same", isDifferentPids( holder, null ) );
-    }
-
-
-    public void test_isDifferentPids_null_notNull()
-    {
-        Object holder = createHolder( null );
-        assertTrue( "Expect not same for one pid not null", isDifferentPids( holder, new String[]
-            { "entry" } ) );
-    }
-
-
-    public void test_isDifferentPids_notNull_null()
-    {
-        Object holder = createHolder( new String[]
-            { "entry" } );
-        assertTrue( "Expect not same for one pid not null", isDifferentPids( holder, null ) );
-    }
-
-
-    public void test_isDifferentPids_notNull_notNull()
-    {
-        final String[] pids10 =
-            { "a", "b" };
-        final String[] pids11 =
-            { "b", "a" };
-        final String[] pids20 =
-            { "a", "c" };
-        final String[] pids30 =
-            { "a", "b", "c" };
-
-        final Object holder10 = createHolder( pids10 );
-        assertFalse( isDifferentPids( holder10, pids10 ) );
-        assertFalse( isDifferentPids( holder10, pids11 ) );
-        assertTrue( isDifferentPids( holder10, pids20 ) );
-        assertTrue( isDifferentPids( holder10, pids30 ) );
-
-        final Object holder20 = createHolder( pids20 );
-        assertTrue( isDifferentPids( holder20, pids10 ) );
-        assertTrue( isDifferentPids( holder20, pids11 ) );
-        assertFalse( isDifferentPids( holder20, pids20 ) );
-        assertTrue( isDifferentPids( holder20, pids30 ) );
-    }
-
-
-    private Object createHolder( final String[] pids )
-    {
-        try
-        {
-            return mshConstructor.newInstance( new Object[]
-                { null, pids } );
-        }
-        catch ( Throwable t )
-        {
-            fail( t.getMessage() );
-            return null; // keep compiler quiet
-        }
-    }
-
-
-    private boolean isDifferentPids( final Object holder, final String[] pids )
-    {
-        try
-        {
-            Object result = msh_isDifferentPids.invoke( holder, new Object[]
-                { pids } );
-            return ( result instanceof Boolean ) && ( ( Boolean ) result ).booleanValue();
-        }
-        catch ( Throwable t )
-        {
-            fail( t.getMessage() );
-            return false; // keep compiler quiet
-        }
-    }
-}
diff --git a/configadmin/src/test/java/org/apache/felix/cm/impl/MockConfigurationManager.java b/configadmin/src/test/java/org/apache/felix/cm/impl/MockConfigurationManager.java
index 31a8bb0..6c044c4 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/impl/MockConfigurationManager.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/impl/MockConfigurationManager.java
@@ -46,7 +46,7 @@
     }
 
 
-    void log( int level, String message, Throwable t )
+    public void log( int level, String message, Throwable t )
     {
         // no logging for now
     }