/* * 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.aries.osgi.functional.test; import org.apache.aries.osgi.functional.OSGi; import org.apache.aries.osgi.functional.OSGiResult; import org.junit.Test; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; 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.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; import java.io.IOException; import java.util.Arrays; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.apache.aries.osgi.functional.OSGi.configuration; import static org.apache.aries.osgi.functional.OSGi.configurations; import static org.apache.aries.osgi.functional.OSGi.just; import static org.apache.aries.osgi.functional.OSGi.onClose; import static org.apache.aries.osgi.functional.OSGi.register; import static org.apache.aries.osgi.functional.OSGi.serviceReferences; import static org.apache.aries.osgi.functional.OSGi.services; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class DSLTest { static BundleContext bundleContext = FrameworkUtil.getBundle( DSLTest.class).getBundleContext(); @Test public void testJust() { AtomicInteger atomicInteger = new AtomicInteger(0); OSGi<Integer> just = just(25); assertEquals(0, atomicInteger.get()); try (OSGiResult<Integer> result = just.run( bundleContext, atomicInteger::set)) { assertEquals(25, atomicInteger.get()); } atomicInteger.set(0); OSGi<Integer> map = just(25).map(s -> s + 5); try (OSGiResult<Integer> result = map.run( bundleContext, atomicInteger::set)) { assertEquals(30, atomicInteger.get()); } atomicInteger.set(0); OSGi<Integer> flatMap = just(25).flatMap(s -> just(s + 10)); try (OSGiResult<Integer> result = flatMap.run( bundleContext, atomicInteger::set)) { assertEquals(35, atomicInteger.get()); } atomicInteger.set(0); OSGi<Integer> filter = just(25).filter(s -> s % 2 == 0); try (OSGiResult<Integer> result = filter.run( bundleContext, atomicInteger::set)) { assertEquals(0, atomicInteger.get()); } atomicInteger.set(0); filter = just(25).filter(s -> s % 2 != 0); try (OSGiResult<Integer> result = filter.run( bundleContext, atomicInteger::set)) { assertEquals(25, atomicInteger.get()); } } @Test public void testServiceReferences() { AtomicReference<ServiceReference<Service>> atomicReference = new AtomicReference<>(); ServiceRegistration<Service> serviceRegistration = null; try( OSGiResult<ServiceReference<Service>> osGiResult = serviceReferences(Service.class). run(bundleContext, atomicReference::set) ) { assertNull(atomicReference.get()); serviceRegistration = bundleContext.registerService( Service.class, new Service(), new Hashtable<>()); assertEquals( serviceRegistration.getReference(), atomicReference.get()); } finally { if (serviceRegistration != null) { serviceRegistration.unregister(); } } } @Test public void testServiceReferencesAndClose() { AtomicReference<ServiceReference<Service>> atomicReference = new AtomicReference<>(); OSGi<ServiceReference<Service>> program = serviceReferences(Service.class).flatMap(ref -> onClose(() -> atomicReference.set(null)). then(just(ref)) ); ServiceRegistration<Service> serviceRegistration = null; try( OSGiResult<?> osGiResult = program.run( bundleContext, atomicReference::set) ) { assertNull(atomicReference.get()); serviceRegistration = bundleContext.registerService( Service.class, new Service(), new Hashtable<>()); assertEquals( serviceRegistration.getReference(), atomicReference.get()); } finally { if (serviceRegistration != null) { serviceRegistration.unregister(); } } assertNull(atomicReference.get()); } @Test public void testConfiguration() throws IOException, InterruptedException { ServiceReference<ConfigurationAdmin> serviceReference = bundleContext.getServiceReference(ConfigurationAdmin.class); ConfigurationAdmin configurationAdmin = bundleContext.getService( serviceReference); AtomicReference<Dictionary<?,?>> atomicReference = new AtomicReference<>(null); Configuration configuration = null; CountDownLatch countDownLatch = new CountDownLatch(1); try(OSGiResult<Dictionary<String, ?>> result = configuration("test.configuration").run( bundleContext, x -> { atomicReference.set(x); countDownLatch.countDown(); })) { assertNull(atomicReference.get()); configuration = configurationAdmin.getConfiguration( "test.configuration"); configuration.update(new Hashtable<>()); countDownLatch.await(10, TimeUnit.SECONDS); assertNotNull(atomicReference.get()); } finally { bundleContext.ungetService(serviceReference); if (configuration != null) { configuration.delete(); } } } @Test public void testConfigurations() throws IOException, InterruptedException { ServiceReference<ConfigurationAdmin> serviceReference = bundleContext.getServiceReference(ConfigurationAdmin.class); ConfigurationAdmin configurationAdmin = bundleContext.getService( serviceReference); AtomicReference<Dictionary<?,?>> atomicReference = new AtomicReference<>(null); CountDownLatch countDownLatch = new CountDownLatch(1); Configuration configuration = null; try(OSGiResult<Dictionary<String, ?>> result = configurations("test.configuration").run( bundleContext, x -> { atomicReference.set(x); countDownLatch.countDown(); })) { assertNull(atomicReference.get()); configuration = configurationAdmin.createFactoryConfiguration( "test.configuration"); configuration.update(new Hashtable<>()); countDownLatch.await(10, TimeUnit.SECONDS); assertNotNull(atomicReference.get()); } finally { bundleContext.ungetService(serviceReference); if (configuration != null) { configuration.delete(); } } } @Test public void testRegister() { assertNull(bundleContext.getServiceReference(Service.class)); Service service = new Service(); OSGiResult<ServiceRegistration<Service>> result = register( Service.class, service, new HashMap<>()). run(bundleContext); ServiceReference<Service> serviceReference = bundleContext.getServiceReference(Service.class); assertEquals(service, bundleContext.getService(serviceReference)); result.close(); assertNull(bundleContext.getServiceReference(Service.class)); } @Test public void testConfigurationsAndRegistrations() throws InvalidSyntaxException, IOException, InterruptedException { ServiceReference<ConfigurationAdmin> serviceReference = bundleContext.getServiceReference(ConfigurationAdmin.class); ConfigurationAdmin configurationAdmin = bundleContext.getService( serviceReference); /* For each factory configuration register a service with the property key set to the value of the property key that comes with the configuration */ OSGi<ServiceRegistration<Service>> program = configurations("test.configuration"). map(d -> d.get("key")).flatMap(key -> register( Service.class, new Service(), new HashMap<String, Object>() {{ put("key", key); }}) ); OSGiResult<ServiceRegistration<Service>> result = program.run( bundleContext); assertEquals( 0, bundleContext.getServiceReferences( Service.class, "(test.configuration=*)").size()); CountDownLatch addedLatch = new CountDownLatch(3); ServiceRegistration<?> addedServiceRegistration = bundleContext.registerService( ManagedServiceFactory.class, new ManagedServiceFactory() { @Override public String getName() { return ""; } @Override public void updated( String s, Dictionary<String, ?> dictionary) throws ConfigurationException { addedLatch.countDown(); } @Override public void deleted(String s) { } }, new Hashtable<String, Object>() {{ put("service.pid", "test.configuration"); }}); CountDownLatch deletedLatch = new CountDownLatch(3); ServiceRegistration<?> deletedServiceRegistration = bundleContext.registerService( ManagedServiceFactory.class, new ManagedServiceFactory() { @Override public String getName() { return ""; } @Override public void updated( String s, Dictionary<String, ?> dictionary) throws ConfigurationException { } @Override public void deleted(String s) { deletedLatch.countDown(); } }, new Hashtable<String, Object>() {{ put("service.pid", "test.configuration"); }}); Configuration configuration = configurationAdmin.createFactoryConfiguration("test.configuration"); configuration.update(new Hashtable<String, Object>(){{ put("key", "service one"); }}); Configuration configuration2 = configurationAdmin.createFactoryConfiguration("test.configuration"); configuration2.update(new Hashtable<String, Object>(){{ put("key", "service two"); }}); Configuration configuration3 = configurationAdmin.createFactoryConfiguration("test.configuration"); configuration3.update(new Hashtable<String, Object>(){{ put("key", "service three"); }}); assertTrue(addedLatch.await(10, TimeUnit.SECONDS)); assertEquals( 1, bundleContext.getServiceReferences( Service.class, "(key=service one)").size()); assertEquals( 1, bundleContext.getServiceReferences( Service.class, "(key=service two)").size()); assertEquals( 1, bundleContext.getServiceReferences( Service.class, "(key=service three)").size()); configuration3.delete(); configuration2.delete(); configuration.delete(); assertTrue(deletedLatch.await(10, TimeUnit.SECONDS)); assertEquals( 0, bundleContext.getServiceReferences( Service.class, "(test.configuration=*)").size()); addedServiceRegistration.unregister(); deletedServiceRegistration.unregister(); result.close(); bundleContext.ungetService(serviceReference); } @Test public void testProgrammaticDependencies() { AtomicBoolean executed = new AtomicBoolean(false); AtomicBoolean closed = new AtomicBoolean(false); String[] filters = { "(key=service one)", "(key=service two)", "(key=service three)" }; OSGi<?> program = onClose(() -> closed.set(true)).foreach( ign -> executed.set(true) ); for (String filter : filters) { program = services(filter).then(program); } OSGiResult<?> result = program.run(bundleContext); try { assertFalse(closed.get()); assertFalse(executed.get()); ServiceRegistration<Service> serviceRegistrationOne = bundleContext.registerService( Service.class, new Service(), new Hashtable<String, Object>() {{ put("key", "service one"); }}); assertFalse(closed.get()); assertFalse(executed.get()); ServiceRegistration<Service> serviceRegistrationTwo = bundleContext.registerService( Service.class, new Service(), new Hashtable<String, Object>() {{ put("key", "service two"); }}); assertFalse(closed.get()); assertFalse(executed.get()); ServiceRegistration<Service> serviceRegistrationThree = bundleContext.registerService( Service.class, new Service(), new Hashtable<String, Object>() {{ put("key", "service three"); }}); assertFalse(closed.get()); assertTrue(executed.get()); serviceRegistrationOne.unregister(); assertTrue(closed.get()); serviceRegistrationTwo.unregister(); serviceRegistrationThree.unregister(); } finally { result.close(); } } private class Service {} }