blob: eb398440d064b920337b9274084870e0da9c0490 [file] [log] [blame]
/*
* 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.integration;
import java.io.IOException;
import java.util.Hashtable;
import junit.framework.TestCase;
import org.apache.felix.cm.integration.helper.ManagedServiceFactoryTestActivator;
import org.apache.felix.cm.integration.helper.ManagedServiceFactoryTestActivator2;
import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator;
import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
@RunWith(JUnit4TestRunner.class)
public class ConfigurationBindingTest extends ConfigurationTestBase
{
static
{
// uncomment to enable debugging of this test class
// paxRunnerVmOption = DEBUG_VM_OPTION;
}
private ConfigListener configListener;
private ServiceRegistration configListenerReg;
@Override
public void setUp()
{
super.setUp();
configListener = new ConfigListener();
configListenerReg = bundleContext.registerService( ConfigurationListener.class.getName(), configListener, null );
}
@Override
public void tearDown() throws BundleException
{
if ( configListenerReg != null )
{
configListenerReg.unregister();
configListenerReg = null;
}
configListener = null;
super.tearDown();
}
@Test
public void test_configuration_unbound_on_uninstall() throws BundleException
{
String pid = "test_configuration_unbound_on_uninstall";
configure( pid );
delay(); // for the event to be distributed
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
// ensure configuration is unbound
final Configuration beforeInstall = getConfiguration( pid );
TestCase.assertNull( beforeInstall.getBundleLocation() );
bundle = installBundle( pid );
// ensure no configuration bound before start
final Configuration beforeStart = getConfiguration( pid );
TestCase.assertNull( beforeInstall.getBundleLocation() );
TestCase.assertNull( beforeStart.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
bundle.start();
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "Activator not started !!", tester );
// give cm time for distribution
delay();
// assert activater has configuration
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// ensure a freshly retrieved object also has the location
final Configuration beforeStop = getConfiguration( pid );
TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );
// check whether bundle context is set on first configuration
TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
bundle.stop();
delay();
// ensure configuration still bound
TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );
// ensure a freshly retrieved object also has the location
final Configuration beforeUninstall = getConfiguration( pid );
TestCase.assertEquals( beforeUninstall.getBundleLocation(), bundle.getLocation() );
bundle.uninstall();
bundle = null;
delay();
// ensure configuration is not bound any more
TestCase.assertNull( beforeInstall.getBundleLocation() );
TestCase.assertNull( beforeStart.getBundleLocation() );
TestCase.assertNull( beforeStop.getBundleLocation() );
TestCase.assertNull( beforeUninstall.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// ensure a freshly retrieved object also does not have the location
final Configuration atEnd = getConfiguration( pid );
TestCase.assertNull( atEnd.getBundleLocation() );
// remove the configuration for good
deleteConfig( pid );
delay();
configListener.assertEvents( ConfigurationEvent.CM_DELETED, 1 );
}
@Test
public void test_configuration_unbound_on_uninstall_with_cm_restart() throws BundleException
{
final String pid = "test_configuration_unbound_on_uninstall_with_cm_restart";
configure( pid );
final Bundle cmBundle = getCmBundle();
// ensure configuration is unbound
final Configuration beforeInstall = getConfiguration( pid );
TestCase.assertNull( beforeInstall.getBundleLocation() );
bundle = installBundle( pid );
// ensure no configuration bound before start
final Configuration beforeStart = getConfiguration( pid );
TestCase.assertNull( beforeInstall.getBundleLocation() );
TestCase.assertNull( beforeStart.getBundleLocation() );
bundle.start();
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "IOActivator not started !!", tester );
// give cm time for distribution
delay();
// assert activater has configuration
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
// ensure a freshly retrieved object also has the location
final Configuration beforeStop = getConfiguration( pid );
TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );
// check whether bundle context is set on first configuration
TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
bundle.stop();
// ensure configuration still bound
TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );
// ensure a freshly retrieved object also has the location
final Configuration beforeUninstall = getConfiguration( pid );
TestCase.assertEquals( beforeUninstall.getBundleLocation(), bundle.getLocation() );
// stop cm bundle now before uninstalling configured bundle
cmBundle.stop();
delay();
// assert configuration admin service is gone
TestCase.assertNull( configAdminTracker.getService() );
// uninstall bundle while configuration admin is stopped
bundle.uninstall();
bundle = null;
// start cm bundle again after uninstallation
cmBundle.start();
delay();
// ensure a freshly retrieved object also does not have the location
// FELIX-1484: this test fails due to bundle location not verified
// at first configuration access
final Configuration atEnd = getConfiguration( pid );
TestCase.assertNull( atEnd.getBundleLocation() );
// remove the configuration for good
deleteConfig( pid );
}
@Test
public void test_not_updated_new_configuration_not_bound_after_bundle_uninstall() throws IOException,
BundleException
{
final String pid = "test_not_updated_new_configuration_not_bound_after_bundle_uninstall";
// create a configuration but do not update with properties
final Configuration newConfig = configure( pid, null, false );
TestCase.assertNull( newConfig.getProperties() );
TestCase.assertNull( newConfig.getBundleLocation() );
// start and settle bundle
bundle = installBundle( pid );
bundle.start();
delay();
// ensure no properties provided to bundle
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "Activator not started !!", tester );
TestCase.assertNull( "Expect no properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
// assert configuration is still unset but bound
TestCase.assertNull( newConfig.getProperties() );
TestCase.assertEquals( bundle.getLocation(), newConfig.getBundleLocation() );
// uninstall bundle, should unbind configuration
bundle.uninstall();
bundle = null;
delay();
// assert configuration is still unset and unbound
TestCase.assertNull( newConfig.getProperties() );
TestCase.assertNull( newConfig.getBundleLocation() );
// remove the configuration for good
deleteConfig( pid );
}
@Test
public void test_create_with_location_unbind_before_service_supply() throws BundleException, IOException
{
final String pid = "test_create_with_location_unbind_before_service_supply";
final String dummyLocation = "http://some/dummy/location";
// 1. create and statically bind the configuration
final Configuration config = configure( pid, dummyLocation, false );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertEquals( dummyLocation, config.getBundleLocation() );
// 2. update configuration
Hashtable<String, String> props = new Hashtable<String, String>();
props.put( PROP_NAME, PROP_NAME );
config.update( props );
TestCase.assertEquals( PROP_NAME, config.getProperties().get( PROP_NAME ) );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertEquals( dummyLocation, config.getBundleLocation() );
// 3. (statically) set location to null
config.setBundleLocation( null );
TestCase.assertNull( config.getBundleLocation() );
// 4. install bundle with service
bundle = installBundle( pid );
bundle.start();
delay();
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "Activator not started !!", tester );
// assert activater has configuration (two calls, one per pid)
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );
bundle.uninstall();
bundle = null;
delay();
// statically bound configurations must remain bound after bundle
// uninstall
TestCase.assertNull( config.getBundleLocation() );
// remove the configuration for good
deleteConfig( pid );
}
@Test
public void test_statically_bound() throws BundleException
{
final String pid = "test_statically_bound";
// install the bundle (we need the location)
bundle = installBundle( pid );
final String location = bundle.getLocation();
// create and statically bind the configuration
configure( pid );
final Configuration config = getConfiguration( pid );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertNull( config.getBundleLocation() );
config.setBundleLocation( location );
TestCase.assertEquals( location, config.getBundleLocation() );
// ensure configuration is settled before starting the bundle
delay();
// expect single config update and location change
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
bundle.start();
// give cm time for distribution
delay();
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "Activator not started !!", tester );
// assert activater has configuration (two calls, one per pid)
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
TestCase.assertEquals( location, config.getBundleLocation() );
// config already statically bound, no change event
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
bundle.uninstall();
bundle = null;
delay();
// statically bound configurations must remain bound after bundle
// uninstall
TestCase.assertEquals( location, config.getBundleLocation() );
// configuration statically bound, no change event
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
// remove the configuration for good
deleteConfig( pid );
delay();
configListener.assertEvents( ConfigurationEvent.CM_DELETED, 1 );
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 0 );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
}
@Test
public void test_static_binding_and_unbinding() throws BundleException
{
final String pid = "test_static_binding_and_unbinding";
final String location = bundleContext.getBundle().getLocation();
// create and statically bind the configuration
configure( pid );
final Configuration config = getConfiguration( pid );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertNull( config.getBundleLocation() );
// first configuration updated event
delay();
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
// bind the configuration
config.setBundleLocation( location );
TestCase.assertEquals( location, config.getBundleLocation() );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// restart CM bundle
final Bundle cmBundle = getCmBundle();
cmBundle.stop();
delay();
cmBundle.start();
// assert configuration still bound
final Configuration configAfterRestart = getConfiguration( pid );
TestCase.assertEquals( pid, configAfterRestart.getPid() );
TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );
// unbind the configuration
configAfterRestart.setBundleLocation( null );
TestCase.assertNull( configAfterRestart.getBundleLocation() );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// restart CM bundle
cmBundle.stop();
delay();
cmBundle.start();
// assert configuration unbound
final Configuration configUnboundAfterRestart = getConfiguration( pid );
TestCase.assertEquals( pid, configUnboundAfterRestart.getPid() );
TestCase.assertNull( configUnboundAfterRestart.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_DELETED, 0 );
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 0 );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
}
@Test
public void test_dynamic_binding_and_unbinding() throws BundleException
{
final String pid = "test_dynamic_binding_and_unbinding";
// create and statically bind the configuration
configure( pid );
final Configuration config = getConfiguration( pid );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertNull( config.getBundleLocation() );
// dynamically bind the configuration
bundle = installBundle( pid );
final String location = bundle.getLocation();
bundle.start();
delay();
TestCase.assertEquals( location, config.getBundleLocation() );
// restart CM bundle
final Bundle cmBundle = getCmBundle();
cmBundle.stop();
delay();
cmBundle.start();
// assert configuration still bound
final Configuration configAfterRestart = getConfiguration( pid );
TestCase.assertEquals( pid, configAfterRestart.getPid() );
TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );
// stop bundle (configuration remains bound !!)
bundle.stop();
delay();
TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );
// restart CM bundle
cmBundle.stop();
delay();
cmBundle.start();
// assert configuration still bound
final Configuration configBoundAfterRestart = getConfiguration( pid );
TestCase.assertEquals( pid, configBoundAfterRestart.getPid() );
TestCase.assertEquals( location, configBoundAfterRestart.getBundleLocation() );
}
@Test
public void test_static_binding() throws BundleException
{
final String pid = "test_static_binding";
// install a bundle to get a location for binding
bundle = installBundle( pid );
final String location = bundle.getLocation();
// create and statically bind the configuration
configure( pid );
final Configuration config = getConfiguration( pid );
TestCase.assertEquals( pid, config.getPid() );
TestCase.assertNull( config.getBundleLocation() );
config.setBundleLocation( location );
TestCase.assertEquals( location, config.getBundleLocation() );
// ensure configuration is settled before starting the bundle
delay();
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
// start the bundle
bundle.start();
delay();
TestCase.assertEquals( location, config.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// assert the configuration is supplied
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( "Activator not started !!", tester );
TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );
// remove the static binding and assert bound (again)
config.setBundleLocation( null );
delay();
TestCase.assertEquals( location, config.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 2 );
// uninstall bundle and assert configuration unbound
bundle.uninstall();
bundle = null;
delay();
TestCase.assertNull( config.getBundleLocation() );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
}
@Test
public void test_two_bundles_one_pid() throws BundleException, IOException
{
// 1. Bundle registers service with pid1
final String pid = "test_two_bundles_one_pid";
final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class );
final String locationA = bundleA.getLocation();
bundleA.start();
delay();
// call back with null
final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNull( tester.props );
TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );
// 2. create new Conf with pid1 and locationA.
final Configuration config = configure( pid, locationA, false );
delay();
// ==> No call back.
TestCase.assertNull( tester.props );
TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );
// 3. Configuration#update(prop) is called.
config.update( theConfig );
delay();
// ==> call back with the prop.
TestCase.assertNotNull( tester.props );
TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );
// 4. Stop BundleA
bundleA.stop();
delay();
// 5. Start BundleA
bundleA.start();
delay();
// ==> call back with the prop.
final ManagedServiceTestActivator tester2 = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( tester2.props );
TestCase.assertEquals( 1, tester2.numManagedServiceUpdatedCalls );
// 6. Configuration#deleted() is called.
config.delete();
delay();
// ==> call back with null.
TestCase.assertNull( tester2.props );
TestCase.assertEquals( 2, tester2.numManagedServiceUpdatedCalls );
// 7. uninstall Bundle A for cleanup.
bundleA.uninstall();
delay();
// Test 2
// 8. BundleA registers ManagedService with pid1.
final Bundle bundleA2 = installBundle( pid, ManagedServiceTestActivator.class );
final String locationA2 = bundleA.getLocation();
bundleA2.start();
delay();
// call back with null
final ManagedServiceTestActivator tester21 = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNull( tester21.props );
TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );
// 9. create new Conf with pid1 and locationB.
final String locationB = "test:locationB/" + pid;
final Configuration configB = configure( pid, locationB, false );
delay();
// ==> No call back.
TestCase.assertNull( tester21.props );
TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );
// 10. Configuration#update(prop) is called.
configB.update( theConfig );
delay();
// ==> No call back because the Conf is not bound to locationA.
TestCase.assertNull( tester21.props );
TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );
}
@Test
public void test_switch_static_binding() throws BundleException
{
// 1. create config with pid and locationA
// 2. update config with properties
final String pid = "test_switch_static_binding";
final String locationA = "test:location/A/" + pid;
final Configuration config = configure( pid, locationA, true );
// 3. register ManagedService ms1 with pid from said locationA
final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.props );
TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + pid;
final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> invisible configuration supplied as null to service ms2
final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.props );
TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
// 5. Call Configuration.setBundleLocation( "locationB" )
config.setBundleLocation( locationB );
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration removed from service ms1
TestCase.assertNull( testerA1.props );
TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
}
@Test
public void test_switch_dynamic_binding() throws BundleException, IOException
{
// 1. create config with pid with null location
// 2. update config with properties
final String pid = "test_switch_dynamic_binding";
final String locationA = "test:location/A/" + pid;
final Configuration config = configure( pid, null, true );
// 3. register ManagedService ms1 with pid from locationA
final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.props );
TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );
// ==> configuration is dynamically bound to locationA
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + pid;
final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> invisible configuration supplied as null to service ms2
final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.props );
TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
// 5. Call Configuration.setBundleLocation( "locationB" )
config.setBundleLocation( locationB );
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration removed from service ms1
TestCase.assertNull( testerA1.props );
TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
// 6. Update configuration now
config.update();
delay();
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
TestCase.assertEquals( 3, testerB1.numManagedServiceUpdatedCalls );
}
@Test
public void test_switch_static_binding_factory() throws BundleException, IOException
{
// 1. create config with pid and locationA
// 2. update config with properties
final String factoryPid = "test_switch_static_binding_factory";
final String locationA = "test:location/A/" + factoryPid;
final Configuration config = createFactoryConfiguration( factoryPid, locationA, true );
final String pid = config.getPid();
// 3. register ManagedService ms1 with pid from said locationA
final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.configs.get( pid ) );
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + factoryPid;
final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> configuration not supplied to service ms2
final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.configs.get( pid ));
TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
// 5. Call Configuration.setBundleLocation( "locationB" )
config.setBundleLocation( locationB );
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration removed from service ms1
TestCase.assertNull( testerA1.configs.get( pid ));
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
delay();
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
@Test
public void test_switch_dynamic_binding_factory() throws BundleException, IOException
{
// 1. create config with pid and locationA
// 2. update config with properties
final String factoryPid = "test_switch_static_binding_factory";
final String locationA = "test:location/A/" + factoryPid;
final Configuration config = createFactoryConfiguration( factoryPid, null, true );
final String pid = config.getPid();
TestCase.assertNull( config.getBundleLocation() );
// 3. register ManagedService ms1 with pid from said locationA
final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.configs.get( pid ) );
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + factoryPid;
final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> configuration not supplied to service ms2
final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.configs.get( pid ));
TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 5. Call Configuration.setBundleLocation( "locationB" )
config.setBundleLocation( locationB );
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration removed from service ms1
TestCase.assertNull( testerA1.configs.get( pid ));
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
delay();
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
@Test
public void test_switch_dynamic_binding_after_uninstall() throws BundleException, IOException
{
// 1. create config with pid with null location
// 2. update config with properties
final String pid = "test_switch_dynamic_binding";
final String locationA = "test:location/A/" + pid;
final Configuration config = configure( pid, null, true );
TestCase.assertNull( config.getBundleLocation() );
// 3. register ManagedService ms1 with pid from locationA
final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.props );
TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );
// ==> configuration is dynamically bound to locationA
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + pid;
final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> invisible configuration supplied as null to service ms2
final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.props );
TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
// 5. Uninstall bundle A
bundleA.uninstall();
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
// 6. Update configuration now
config.update();
delay();
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.props );
TestCase.assertEquals( 3, testerB1.numManagedServiceUpdatedCalls );
}
@Test
public void test_switch_dynamic_binding_factory_after_uninstall() throws BundleException, IOException
{
// 1. create config with pid and locationA
// 2. update config with properties
final String factoryPid = "test_switch_static_binding_factory";
final String locationA = "test:location/A/" + factoryPid;
final Configuration config = createFactoryConfiguration( factoryPid, null, true );
final String pid = config.getPid();
TestCase.assertNull( config.getBundleLocation() );
// 3. register ManagedService ms1 with pid from said locationA
final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
bundleA.start();
delay();
// ==> configuration supplied to the service ms1
final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
TestCase.assertNotNull( testerA1.configs.get( pid ) );
TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 4. register ManagedService ms2 with pid from locationB
final String locationB = "test:location/B/" + factoryPid;
final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
bundleB.start();
delay();
// ==> configuration not supplied to service ms2
final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
TestCase.assertNull( testerB1.configs.get( pid ));
TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
TestCase.assertEquals( locationA, config.getBundleLocation() );
// 5. Uninstall bundle A
bundleA.uninstall();
delay();
// ==> configuration is bound to locationB
TestCase.assertEquals( locationB, config.getBundleLocation() );
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );
// 6. Update configuration now
config.update();
delay();
// ==> configuration supplied to the service ms2
TestCase.assertNotNull( testerB1.configs.get( pid ) );
TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
}
@Test
public void test_location_changed_events() throws BundleException, IOException
{
String pid = "test_location_changed_events";
configure( pid );
delay();
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
// ensure configuration is unbound
final Configuration config = getConfiguration( pid );
TestCase.assertNull( config.getBundleLocation() );
bundle = installBundle( pid );
bundle.start();
delay();
// ensure no configuration bound before start
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// uninstall the bundle, dynamic location changed
bundle.uninstall();
bundle = null;
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// change the location
config.setBundleLocation( "some_location_1" );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// change the location
config.setBundleLocation( "some_location_2" );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// remove configuration, delete event
config.delete();
delay();
configListener.assertEvents( ConfigurationEvent.CM_DELETED, 1 );
// no more events
delay();
configListener.assertEvents( ConfigurationEvent.CM_DELETED, 0 );
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 0 );
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 0 );
}
/**
* Tests configuration dynamic binding. See FELIX-3360.
*/
@SuppressWarnings({ "serial", "javadoc" })
@Test
public void test_dynamic_binding_getConfiguration_pid() throws BundleException, IOException {
String ignoredPid = "test_dynamic_binding_getConfiguration_pid_ignored";
String pid1 = "test_dynamic_binding_getConfiguration_pid_1";
String pid2 = "test_dynamic_binding_getConfiguration_pid_2";
// ensure configuration is unbound
configure( pid1 );
delay();
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
bundle = installBundle( ignoredPid );
bundle.start();
delay();
// ensure config1 unbound
Configuration config1 = getConfiguration( pid1 );
TestCase.assertNull( config1.getBundleLocation() );
ServiceReference<ConfigurationAdmin> sr = bundle.getBundleContext().getServiceReference( ConfigurationAdmin.class );
ConfigurationAdmin bundleCa = bundle.getBundleContext().getService( sr );
// ensure dynamic binding
Configuration bundleConfig1 = bundleCa.getConfiguration( pid1 );
TestCase.assertEquals( bundle.getLocation(), bundleConfig1.getBundleLocation() );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// create config2; ensure dynamic binding
Configuration bundleConfig2 = bundleCa.getConfiguration( pid2 );
TestCase.assertNull(bundleConfig2.getProperties());
TestCase.assertEquals( bundle.getLocation(), bundleConfig2.getBundleLocation() );
bundleConfig2.update( new Hashtable<String, String>()
{
{
put( "key", "value" );
}
} );
// uninstall the bundle, 2 dynamic locations changed
bundle.uninstall();
bundle = null;
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 2 );
bundleConfig1 = getConfiguration( pid1 );
TestCase.assertNull( bundleConfig1.getBundleLocation() );
bundleConfig2 = getConfiguration( pid2 );
TestCase.assertNull(bundleConfig2.getBundleLocation());
bundleConfig1.delete();
bundleConfig2.delete();
}
/**
* Tests factory configuration dynamic binding. See FELIX-3360.
*/
@SuppressWarnings({ "javadoc", "serial" })
@Test
public void test_dynamic_binding_createFactoryConfiguration_pid() throws BundleException, IOException {
String ignoredPid = "test_dynamic_binding_createFactoryConfiguration_pid_ignored";
String pid1 = null;
String pid2 = null;
String factoryPid1 = "test_dynamic_binding_createFactoryConfiguration_pid_1";
String factoryPid2 = "test_dynamic_binding_createFactoryConfiguration_pid_2";
// ensure configuration is unbound
pid1 = createFactoryConfiguration( factoryPid1 ).getPid();
delay();
configListener.assertEvents( ConfigurationEvent.CM_UPDATED, 1 );
bundle = installBundle( ignoredPid );
bundle.start();
delay();
// ensure config1 unbound
Configuration config1 = getConfiguration( pid1 );
TestCase.assertNull( config1.getBundleLocation() );
ServiceReference<ConfigurationAdmin> sr = bundle.getBundleContext().getServiceReference( ConfigurationAdmin.class );
ConfigurationAdmin bundleCa = bundle.getBundleContext().getService( sr );
// ensure dynamic binding
Configuration bundleConfig1 = bundleCa.getConfiguration( pid1 );
TestCase.assertEquals( bundle.getLocation(), bundleConfig1.getBundleLocation() );
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 1 );
// create config2; ensure dynamic binding
Configuration bundleConfig2 = bundleCa.createFactoryConfiguration( factoryPid2 );
pid2 = bundleConfig2.getPid();
TestCase.assertNull(bundleConfig2.getProperties());
TestCase.assertEquals( bundle.getLocation(), bundleConfig2.getBundleLocation() );
bundleConfig2.update( new Hashtable<String, String>()
{
{
put( "key", "value" );
}
} );
// uninstall the bundle, 2 dynamic locations changed
bundle.uninstall();
bundle = null;
delay();
configListener.assertEvents( ConfigurationEvent.CM_LOCATION_CHANGED, 2 );
bundleConfig1 = getConfiguration( pid1 );
TestCase.assertNull( bundleConfig1.getBundleLocation() );
bundleConfig2 = getConfiguration( pid2 );
TestCase.assertNull(bundleConfig2.getBundleLocation());
bundleConfig1.delete();
bundleConfig2.delete();
}
private static class ConfigListener implements ConfigurationListener {
private int[] events = new int[3];
public void configurationEvent( ConfigurationEvent event )
{
events[event.getType()-1]++;
}
void assertEvents( final int type, final int numEvents )
{
TestCase.assertEquals( "Events of type " + type, numEvents, events[type - 1] );
events[type - 1] = 0;
}
void reset()
{
for ( int i = 0; i < events.length; i++ )
{
events[i] = 0;
}
}
}
}