blob: d7727d3d0a40a6f7de8d40d253d4d437942a1f8a [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.dm.impl;
import static org.mockito.Mockito.mock;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.impl.ConfigurationDependencyImplTest.AManagedService;
import org.apache.felix.dm.impl.ConfigurationDependencyImplTest.FancyService;
import org.apache.felix.dm.impl.ConfigurationDependencyImplTest.MyConfiguration;
import org.apache.felix.dm.impl.ConfigurationDependencyImplTest.PlainService;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.service.cm.ManagedServiceFactory;
import test.Ensure;
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class FactoryConfigurationAdapterImplTest {
private static final String CONF_PID = "bogus";
@Test
public void testDoNotInvokeFancyUpdatedMethodWithWrongSignatureOk() throws Exception {
Ensure ensure = createEnsure();
FancyService service = new FancyService(ensure);
FactoryConfigurationAdapterImpl cdi = createConfigurationDependency(service, Map.class);
ensure.step(1);
((ManagedServiceFactory) cdi.m_component.getInstance()).updated(CONF_PID, (Dictionary<String, ?>) createDictionary());
TimeUnit.SECONDS.sleep(1L);
// Our step shouldn't be changed...
ensure.waitForStep(1, 1000);
}
@Test
public void testInvokeFancyUpdatedMethodOk() throws Exception {
Ensure ensure = createEnsure();
FancyService service = new FancyService(ensure);
FactoryConfigurationAdapterImpl cdi = createConfigurationDependency(service, MyConfiguration.class);
((ManagedServiceFactory) cdi.m_component.getInstance()).updated(CONF_PID, (Dictionary<String, ?>) createDictionary());
ensure.waitForStep(1, 1000);
((ManagedServiceFactory) cdi.m_component.getInstance()).deleted(CONF_PID);
ensure.waitForStep(2, 1000);
}
@Test
public void testInvokeManagedServiceUpdatedMethodOk() throws Exception {
Ensure ensure = createEnsure();
AManagedService service = new AManagedService(ensure);
FactoryConfigurationAdapterImpl cdi = createConfigurationDependency(service);
((ManagedServiceFactory) cdi.m_component.getInstance()).updated(CONF_PID, (Dictionary<String, ?>) createDictionary());
ensure.waitForStep(1, 1000);
((ManagedServiceFactory) cdi.m_component.getInstance()).deleted(CONF_PID);
ensure.waitForStep(2, 1000);
}
@Test
public void testInvokePlainUpdatedMethodOk() throws Exception {
Ensure ensure = createEnsure();
PlainService service = new PlainService(ensure);
FactoryConfigurationAdapterImpl cdi = createConfigurationDependency(service);
((ManagedServiceFactory) cdi.m_component.getInstance()).updated(CONF_PID, (Dictionary<String, ?>) createDictionary());
ensure.waitForStep(1, 1000);
((ManagedServiceFactory) cdi.m_component.getInstance()).deleted(CONF_PID);
ensure.waitForStep(2, 1000);
}
private FactoryConfigurationAdapterImpl createConfigurationDependency(Object service) {
return createConfigurationDependency(service, null);
}
private FactoryConfigurationAdapterImpl createConfigurationDependency(Object service, Class<?> configType) {
BundleContext bc = mock(BundleContext.class);
DependencyManager dm = new DependencyManager(bc);
Component result = dm.createFactoryConfigurationAdapterService("does.not.matter", "updated", false, service, configType);
// Normally, when creating a factory pid adapter, you specify the class of the adapter implementation which will be instantiated
// for each created factory pid. To do so, you invoke the setImplementation(Object impl) method, and this methods
// accepts a class parameter, or an object instance. Usually, you always pass a class, because the intent of a factory pid adapter is to
// create a component instance for each created factory pid. But in our case, the "service" parameter represents our adapter instance,
// so just use it as the factory adapter implementation instance:
result.setImplementation(service);
// *Important note:* the semantic of the factory conf pid adapter is really similar to a ManagedServiceFactory:
// - when the factory pid is created, a component is created; called in updated; and called in start().
// - when the factory pid is updated, the component is called in updated().
// - but when the factory pid is removed, updated(null) is not invoked (unlike in case of ConfigurationDependency), and the component is simply
// stopped. This is actually the same semantic as ManagedServiceFactory: when factory pid is removed, ManagedServiceFactory.deleted() is called
// and the deleted() method is assumed to stop and unregister the service that was registered for the pid being removed.
dm.add(result);
return (FactoryConfigurationAdapterImpl) result;
}
private Dictionary<String, Object> createDictionary() {
Dictionary<String, Object> result = new Hashtable<>();
result.put("true", "true");
result.put("value", "42");
result.put("longValue", "1234567890");
result.put("pi", "3.141");
result.put("argArray", "[a, b, c]");
result.put("argList", "[d, e, f]");
result.put("map.foo", "bar");
result.put("map.qux", "123");
result.put("map.quu", "[x, y, z]");
result.put("message", "hello world!");
return result;
}
private Ensure createEnsure() {
return new Ensure(false);
}
}