FELIX-1488 dynamic binding must not be removed before initiating the
configuration deletion callback, otherwise the callback does not
take place.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@805678 13f79535-47bb-0310-9956-ffa450edef68
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 9454ae6..d22214b 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
@@ -123,7 +123,6 @@
     {
         this.isDeleted = true;
         getPersistenceManager().delete( this.getPid() );
-        setDynamicBundleLocation( null );
         getConfigurationManager().deleted( this );
     }
 
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 6d15ae8..1defa50 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
@@ -1473,16 +1473,19 @@
     private class DeleteConfiguration implements Runnable
     {
 
-        private ConfigurationImpl config;
-        private String pid;
-        private String factoryPid;
+        private final String pid;
+        private final String factoryPid;
+        private final String configLocation;
 
 
         DeleteConfiguration( ConfigurationImpl config )
         {
-            this.config = config;
             this.pid = config.getPid();
             this.factoryPid = config.getFactoryPid();
+            this.configLocation = config.getBundleLocation();
+
+            // immediately unbind the configuration
+            config.setDynamicBundleLocation( null );
         }
 
 
@@ -1490,8 +1493,6 @@
         {
             try
             {
-                final String configLocation = config.getBundleLocation();
-
                 if ( factoryPid == null )
                 {
                     ServiceReference[] srList = bundleContext.getServiceReferences( ManagedService.class.getName(), "("
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
index 1a4257f..3eb10f5 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
@@ -19,13 +19,20 @@
 package org.apache.felix.cm.integration;
 
 
+import java.io.IOException;
+import java.util.Dictionary;
+
 import junit.framework.TestCase;
 
+import org.apache.felix.cm.integration.helper.ManagedServiceFactoryTestActivator;
 import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 
 @RunWith(JUnit4TestRunner.class)
@@ -33,6 +40,146 @@
 {
 
     @Test
+    public void test_basic_configuration_configure_then_start() throws BundleException, IOException
+    {
+        // 1. create config with pid and locationA
+        // 2. update config with properties
+        final String pid = "test_basic_configuration_configure_then_start";
+        final Configuration config = configure( pid, null, true );
+
+        // 3. register ManagedService ms1 with pid from said locationA
+        bundle = installBundle( pid, ManagedServiceTestActivator.class );
+        bundle.start();
+        delay();
+
+        // ==> configuration supplied to the service ms1
+        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
+        TestCase.assertNotNull( tester.props );
+        TestCase.assertEquals( pid, tester.props.get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.props.get( PROP_NAME ) );
+        TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );
+
+        // delete
+        config.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.props );
+        TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );
+    }
+
+
+    @Test
+    public void test_basic_configuration_start_then_configure() throws BundleException, IOException
+    {
+        final String pid = "test_basic_configuration_start_then_configure";
+
+        // 1. register ManagedService ms1 with pid from said locationA
+        bundle = installBundle( pid, ManagedServiceTestActivator.class );
+        bundle.start();
+        delay();
+
+        // 1. create config with pid and locationA
+        // 2. update config with properties
+        final Configuration config = configure( pid, null, true );
+        delay();
+
+        // ==> configuration supplied to the service ms1
+        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
+        TestCase.assertNotNull( tester.props );
+        TestCase.assertEquals( pid, tester.props.get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.props.get( PROP_NAME ) );
+        TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );
+
+        // delete
+        config.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.props );
+        TestCase.assertEquals( 3, tester.numManagedServiceUpdatedCalls );
+    }
+
+
+    @Test
+    public void test_basic_configuration_factory_configure_then_start() throws BundleException, IOException
+    {
+        final String factoryPid = "test_basic_configuration_factory_configure_then_start";
+        bundle = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class );
+        bundle.start();
+        delay();
+
+        final Configuration config = createFactoryConfiguration( factoryPid, null, true );
+        final String pid = config.getPid();
+        delay();
+
+        // ==> configuration supplied to the service ms1
+        final ManagedServiceFactoryTestActivator tester = ManagedServiceFactoryTestActivator.INSTANCE;
+        Dictionary<?, ?> props = tester.configs.get( pid );
+        TestCase.assertNotNull( props );
+        TestCase.assertEquals( pid, props.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid, props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props.get( PROP_NAME ) );
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // delete
+        config.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.configs.get( pid ));
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryDeleteCalls );
+    }
+
+
+    @Test
+    public void test_basic_configuration_factory_start_then_configure() throws BundleException, IOException
+    {
+        // 1. create config with pid and locationA
+        // 2. update config with properties
+        final String factoryPid = "test_basic_configuration_factory_start_then_configure";
+        final Configuration config = createFactoryConfiguration( factoryPid, null, true );
+        final String pid = config.getPid();
+
+        // 3. register ManagedService ms1 with pid from said locationA
+        bundle = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class );
+        bundle.start();
+        delay();
+
+        // ==> configuration supplied to the service ms1
+        final ManagedServiceFactoryTestActivator tester = ManagedServiceFactoryTestActivator.INSTANCE;
+        Dictionary<?, ?> props = tester.configs.get( pid );
+        TestCase.assertNotNull( props );
+        TestCase.assertEquals( pid, props.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid, props.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props.get( PROP_NAME ) );
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // delete
+        config.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.configs.get( pid ));
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 1, tester.numManagedServiceFactoryDeleteCalls );
+    }
+
+
+    @Test
     public void test_start_bundle_configure_stop_start_bundle() throws BundleException
     {
         String pid = "test_start_bundle_configure_stop_start_bundle";