| /* |
| * 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.ipojo.runtime.core; |
| |
| import org.apache.felix.ipojo.ComponentInstance; |
| import org.apache.felix.ipojo.handlers.configuration.ConfigurationHandlerDescription; |
| import org.apache.felix.ipojo.handlers.configuration.ConfigurationListener; |
| import org.apache.felix.ipojo.runtime.core.services.FooService; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.osgi.framework.ServiceReference; |
| |
| import java.util.*; |
| |
| import static org.junit.Assert.*; |
| |
| /** |
| * Test that the ConfigurationHandler calls the ConfigurationListeners when watched instance is reconfigured. |
| */ |
| public class TestListeners extends Common { |
| |
| /** |
| * The number of reconfigurations, incremented by the {@code CountingListener}s. |
| */ |
| int updates = 0; |
| |
| /** |
| * The {@code instance} arguments received by the {@code AppendingListener}s. |
| */ |
| List<ComponentInstance> instances = new ArrayList<ComponentInstance>(); |
| |
| /** |
| * The {@code configuration} arguments received by the {@code AppendingListener}s. |
| */ |
| List<Map<String, Object>> configs = new ArrayList<Map<String, Object>>(); |
| |
| /** |
| * The tested component instance. |
| */ |
| ComponentInstance fooProvider; |
| |
| /** |
| * The configuration handler description of the tested component instance. |
| */ |
| ConfigurationHandlerDescription fooConfig; |
| |
| /** |
| * The service provided by the tested component instance. |
| */ |
| FooService foo; |
| |
| @Before |
| public void setUp() { |
| Properties p = new Properties(); |
| p.put("instance.name", "FooProvider-42"); |
| p.put("int", 4); |
| p.put("boolean", false); |
| p.put("string", "bar"); |
| p.put("strAProp", new String[]{"bar", "foo"}); |
| p.put("intAProp", new int[]{1, 2, 3}); |
| fooProvider = ipojoHelper.createComponentInstance("CONFIG-FooProviderType-ConfUpdated", p); |
| fooConfig = (ConfigurationHandlerDescription) fooProvider.getInstanceDescription() |
| .getHandlerDescription("org.apache.felix.ipojo:properties"); |
| |
| // Get the service |
| ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "FooProvider-42"); |
| foo = (FooService) osgiHelper.getRawServiceObject(ref); |
| } |
| |
| @After |
| public void tearDown() { |
| fooConfig = null; |
| fooProvider.dispose(); |
| fooProvider = null; |
| } |
| |
| /** |
| * A ConfigurationListener that just count its calls. |
| */ |
| private class CountingListener implements ConfigurationListener { |
| public void configurationChanged(ComponentInstance instance, Map<String, Object> configuration) { |
| updates++; |
| } |
| } |
| |
| /** |
| * A ConfigurationListener that just fails. |
| * <p> |
| * Used to ensure that a failing listener does not prevent the following listeners to be called. |
| * </p> |
| */ |
| private class ThrowingListener implements ConfigurationListener { |
| public void configurationChanged(ComponentInstance instance, Map<String, Object> configuration) { |
| throw new RuntimeException("I'm bad"); |
| } |
| } |
| |
| /** |
| * A ConfigurationListener that just appends its arguments. |
| */ |
| private class AppendingListener implements ConfigurationListener { |
| public void configurationChanged(ComponentInstance instance, Map<String, Object> configuration) { |
| instances.add(instance); |
| configs.add(configuration); |
| } |
| } |
| |
| /** |
| * Test that the listeners registered on the tested instance are called when the instance is reconfigured. |
| */ |
| @Test |
| public void testConfigurationListener() { |
| // Register listeners |
| ConfigurationListener l1 = new CountingListener(); |
| fooConfig.addListener(l1); |
| ConfigurationListener l2 = new ThrowingListener(); |
| fooConfig.addListener(l2); |
| ConfigurationListener l3 = new AppendingListener(); |
| fooConfig.addListener(l3); |
| |
| // Trigger a manual reconfiguration |
| Hashtable<String, Object> conf = new Hashtable<String, Object>(); |
| conf.put("int", 40); |
| conf.put("boolean", true); |
| conf.put("string", "saloon"); |
| conf.put("strAProp", new String[]{"bar", "bad"}); |
| conf.put("intAProp", new int[]{21, 22, 23}); |
| fooProvider.reconfigure(conf); |
| |
| // Check the listeners has been called + check the arguments. |
| assertEquals(1, updates); |
| |
| assertEquals(1, instances.size()); |
| assertSame(fooProvider, instances.get(0)); |
| |
| assertEquals(1, configs.size()); |
| Map<String, Object> configMap = configs.get(0); |
| assertEquals(5, configMap.size()); |
| assertEquals(40, configMap.get("int")); |
| assertEquals(true, configMap.get("boolean")); |
| assertEquals("saloon", configMap.get("string")); |
| assertArrayEquals(new String[]{"bar", "bad"}, (String[]) configMap.get("strAProp")); |
| assertArrayEquals(new int[]{21, 22, 23}, (int[]) configMap.get("intAProp")); |
| |
| // Trigger a POJO internal "reconfiguration". |
| // It should not trigger any reconfiguration event. |
| foo.foo(); |
| |
| // Check nothing has changed in the listeners |
| assertEquals(1, updates); |
| assertEquals(1, instances.size()); |
| assertEquals(1, configs.size()); |
| |
| // Unregister the listeners |
| fooConfig.removeListener(l1); |
| fooConfig.removeListener(l2); |
| fooConfig.removeListener(l3); |
| |
| // Trigger a manual reconfiguration |
| conf.put("int", 40); |
| conf.put("boolean", true); |
| conf.put("string", "saloon"); |
| conf.put("strAProp", new String[]{"bar", "bad"}); |
| conf.put("intAProp", new int[]{21, 22, 23}); |
| fooProvider.reconfigure(conf); |
| |
| // Check nothing has changed in the listeners, since they are all removed |
| assertEquals(1, updates); |
| assertEquals(1, instances.size()); |
| assertEquals(1, configs.size()); |
| } |
| |
| @Test(expected = NullPointerException.class) |
| public void testNullProvidedServiceListener() { |
| // Should fail! |
| fooConfig.addListener(null); |
| } |
| |
| /** |
| * This test was initially expecting a NoSuchElementException, in 1.11.2, we changed the method to ignore missing |
| * listeners. |
| */ |
| @Test |
| public void testRemoveNonexistentProvidedServiceListener() { |
| fooConfig.removeListener(new ThrowingListener()); |
| } |
| } |