/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.registry.internal.test; import com.liferay.registry.Registry; import com.liferay.registry.RegistryUtil; import com.liferay.registry.ServiceReference; import com.liferay.registry.ServiceTrackerCustomizer; import com.liferay.registry.collections.ServiceReferenceMapper; import com.liferay.registry.collections.ServiceTrackerCollections; import com.liferay.registry.collections.ServiceTrackerMap; import com.liferay.registry.internal.RegistryWrapper; import com.liferay.registry.internal.TrackedOne; import com.liferay.registry.internal.TrackedTwo; import java.util.Collection; import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.test.api.ArquillianResource; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceRegistration; /** * @author Carlos Sierra Andrés */ @RunWith(Arquillian.class) public class ObjectServiceTrackerMapTest { @Before public void setUp() throws BundleException { bundle.start(); _bundleContext = bundle.getBundleContext(); } @After public void tearDown() throws BundleException { bundle.stop(); if (_serviceTrackerMap != null) { _serviceTrackerMap.close(); _serviceTrackerMap = null; } } @Test public void testContainsKey() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration3 = registerService(new TrackedOne(), "aTarget2"); ServiceRegistration<TrackedOne> serviceRegistration4 = registerService(new TrackedOne(), "aTarget2"); Assert.assertTrue(serviceTrackerMap.containsKey("aTarget1")); Assert.assertTrue(serviceTrackerMap.containsKey("aTarget2")); Assert.assertFalse(serviceTrackerMap.containsKey("aTarget3")); Assert.assertFalse(serviceTrackerMap.containsKey("")); try { serviceTrackerMap.containsKey(null); Assert.fail(); } catch (NullPointerException npe) { } serviceRegistration1.unregister(); serviceRegistration2.unregister(); serviceRegistration3.unregister(); serviceRegistration4.unregister(); } } @Test public void testGetServiceAfterRemoval() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration = registerService(new TrackedOne()); Assert.assertNotNull(serviceTrackerMap.getService("aTarget")); serviceRegistration.unregister(); Assert.assertNull(serviceTrackerMap.getService("aTarget")); } } @Test public void testGetServiceGetsReplacedAfterRemoval() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { TrackedOne trackedOne1 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(trackedOne1, 2); TrackedOne trackedOne2 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(trackedOne2, 1); Assert.assertEquals( trackedOne1, serviceTrackerMap.getService("aTarget")); serviceRegistration1.unregister(); Assert.assertEquals( trackedOne2, serviceTrackerMap.getService("aTarget")); serviceRegistration2.unregister(); } } @Test public void testGetServiceGetsReplacedAfterRemovalInverseOrder() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { TrackedOne trackedOne2 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(trackedOne2, 1); TrackedOne trackedOne1 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(trackedOne1, 2); Assert.assertEquals( trackedOne1, serviceTrackerMap.getService("aTarget")); serviceRegistration2.unregister(); Assert.assertEquals( trackedOne2, serviceTrackerMap.getService("aTarget")); serviceRegistration1.unregister(); } } @Test public void testGetServiceIsNullAfterDeregistration() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(new TrackedOne()); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(new TrackedOne()); ServiceRegistration<TrackedOne> serviceRegistration3 = registerService(new TrackedOne()); Assert.assertNotNull(serviceTrackerMap.getService("aTarget")); serviceRegistration1.unregister(); serviceRegistration2.unregister(); serviceRegistration3.unregister(); Assert.assertNull(serviceTrackerMap.getService("aTarget")); } } @Test public void testGetServiceWithCustomResolver() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = ServiceTrackerCollections.openSingleValueMap( TrackedOne.class, "(&(other=*)(target=*))", new ServiceReferenceMapper<String, TrackedOne>() { @Override public void map( ServiceReference<TrackedOne> serviceReference, Emitter<String> keys) { keys.emit( serviceReference.getProperty("other") + " - " + serviceReference.getProperty("target")); } })) { Dictionary<String, String> properties = new Hashtable<>(); properties.put("other", "aProperty"); properties.put("target", "aTarget"); ServiceRegistration<TrackedOne> serviceRegistration = _bundleContext.registerService( TrackedOne.class, new TrackedOne(), properties); Assert.assertNotNull( serviceTrackerMap.getService("aProperty - aTarget")); serviceRegistration.unregister(); } } @Test public void testGetServiceWithIncorrectKey() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { registerService(new TrackedOne(), "anotherTarget"); Assert.assertNull(serviceTrackerMap.getService("aTarget")); } } @Test public void testGetServiceWithServiceCustomizer() { final Registry registry = RegistryUtil.getRegistry(); try (ServiceTrackerMap<String, TrackedTwo> serviceTrackerMap = ServiceTrackerCollections.openSingleValueMap( TrackedOne.class, "target", new ServiceTrackerCustomizer<TrackedOne, TrackedTwo>() { @Override public TrackedTwo addingService( ServiceReference<TrackedOne> serviceReference) { return new TrackedTwo( registry.getService(serviceReference)); } @Override public void modifiedService( ServiceReference<TrackedOne> serviceReference, TrackedTwo service) { removedService(serviceReference, service); } @Override public void removedService( ServiceReference<TrackedOne> serviceReference, TrackedTwo service) { registry.ungetService(serviceReference); } })) { TrackedOne trackedOne1 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(trackedOne1, "trackedOne1"); TrackedOne trackedOne2 = new TrackedOne(); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(trackedOne2, "trackedOne2"); TrackedTwo trackedTwo1 = serviceTrackerMap.getService( "trackedOne1"); Assert.assertEquals(trackedOne1, trackedTwo1.getTrackedOne()); TrackedTwo trackedTwo2 = serviceTrackerMap.getService( "trackedOne2"); Assert.assertEquals(trackedOne2, trackedTwo2.getTrackedOne()); serviceRegistration1.unregister(); serviceRegistration2.unregister(); } } @Test public void testGetServiceWithServiceCustomizerAndServiceReferenceMapper() { final Registry registry = RegistryUtil.getRegistry(); try (ServiceTrackerMap<String, TrackedTwo> serviceTrackerMap = ServiceTrackerCollections.openSingleValueMap( TrackedOne.class, "(target=*)", new ServiceReferenceMapper<String, TrackedOne>() { @Override public void map( ServiceReference<TrackedOne> serviceReference, Emitter<String> emitter) { TrackedOne service = registry.getService( serviceReference); String targetProperty = (String)serviceReference.getProperty("target"); emitter.emit( targetProperty + "-" + service.getKey()); registry.ungetService(serviceReference); } }, new ServiceTrackerCustomizer<TrackedOne, TrackedTwo>() { @Override public TrackedTwo addingService( ServiceReference<TrackedOne> serviceReference) { return new TrackedTwo( registry.getService(serviceReference)); } @Override public void modifiedService( ServiceReference<TrackedOne> serviceReference, TrackedTwo service) { removedService(serviceReference, service); } @Override public void removedService( ServiceReference<TrackedOne> serviceReference, TrackedTwo service) { registry.ungetService(serviceReference); } })) { TrackedOne trackedOne1 = new TrackedOne("1"); ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(trackedOne1, "trackedOne1"); TrackedOne trackedOne2 = new TrackedOne("2"); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(trackedOne2, "trackedOne2"); TrackedTwo trackedTwo1 = serviceTrackerMap.getService( "trackedOne1-1"); Assert.assertEquals(trackedOne1, trackedTwo1.getTrackedOne()); TrackedTwo trackedTwo2 = serviceTrackerMap.getService( "trackedOne2-2"); Assert.assertEquals(trackedOne2, trackedTwo2.getTrackedOne()); serviceRegistration1.unregister(); serviceRegistration2.unregister(); } } @Test public void testGetServiceWithSimpleRegistration() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration = registerService(new TrackedOne()); Assert.assertNotNull(serviceTrackerMap.getService("aTarget")); serviceRegistration.unregister(); } } @Test public void testKeySet() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration3 = registerService(new TrackedOne(), "aTarget2"); ServiceRegistration<TrackedOne> serviceRegistration4 = registerService(new TrackedOne(), "aTarget2"); Set<String> targets = new HashSet<>(); targets.add("aTarget1"); targets.add("aTarget2"); Assert.assertEquals(targets, serviceTrackerMap.keySet()); serviceRegistration1.unregister(); serviceRegistration2.unregister(); serviceRegistration3.unregister(); serviceRegistration4.unregister(); } } @Test public void testKeySetReturnsUnmodifiableSet() { try (ServiceTrackerMap<String, TrackedOne> serviceTrackerMap = createServiceTrackerMap()) { ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(new TrackedOne(), "aTarget1"); ServiceRegistration<TrackedOne> serviceRegistration3 = registerService(new TrackedOne(), "aTarget2"); ServiceRegistration<TrackedOne> serviceRegistration4 = registerService(new TrackedOne(), "aTarget2"); Set<String> keySet = serviceTrackerMap.keySet(); try { keySet.remove("aTarget1"); Assert.fail(); } catch (UnsupportedOperationException uoe) { } serviceRegistration1.unregister(); serviceRegistration2.unregister(); serviceRegistration3.unregister(); serviceRegistration4.unregister(); } } @Test public void testUnkeyedServiceReferencesBalanceRefCount() { RegistryWrapper registryWrapper = getRegistryWrapper(); try (ServiceTrackerMap<TrackedOne, TrackedOne> serviceTrackerMap = ServiceTrackerCollections.openSingleValueMap( TrackedOne.class, null, new ServiceReferenceMapper<TrackedOne, TrackedOne>() { @Override public void map( ServiceReference<TrackedOne> serviceReference, Emitter<TrackedOne> emitter) { } })) { ServiceRegistration<TrackedOne> serviceRegistration1 = registerService(new TrackedOne()); ServiceRegistration<TrackedOne> serviceRegistration2 = registerService(new TrackedOne()); Map<ServiceReference<?>, AtomicInteger> serviceReferenceCountsMap = registryWrapper.getServiceReferenceCountsMap(); Collection<AtomicInteger> serviceReferenceCounts = serviceReferenceCountsMap.values(); Assert.assertEquals( serviceReferenceCounts.toString(), 0, serviceReferenceCounts.size()); serviceRegistration1.unregister(); serviceRegistration2.unregister(); Assert.assertEquals( serviceReferenceCounts.toString(), 0, serviceReferenceCounts.size()); } finally { RegistryUtil.setRegistry(registryWrapper.getWrappedRegistry()); } } @ArquillianResource public Bundle bundle; protected ServiceTrackerMap<String, TrackedOne> createServiceTrackerMap() { return ServiceTrackerCollections.openSingleValueMap( TrackedOne.class, "target"); } protected RegistryWrapper getRegistryWrapper() { Registry registry = RegistryUtil.getRegistry(); RegistryWrapper registryWrapper = new RegistryWrapper(registry); RegistryUtil.setRegistry(registryWrapper); return registryWrapper; } protected ServiceRegistration<TrackedOne> registerService( TrackedOne trackedOne) { return registerService(trackedOne, "aTarget"); } protected ServiceRegistration<TrackedOne> registerService( TrackedOne trackedOne, int ranking) { return registerService(trackedOne, ranking, "aTarget"); } protected ServiceRegistration<TrackedOne> registerService( TrackedOne trackedOne, int ranking, String target) { Dictionary<String, Object> properties = new Hashtable<>(); properties.put("service.ranking", ranking); properties.put("target", target); return _bundleContext.registerService( TrackedOne.class, trackedOne, properties); } protected ServiceRegistration<TrackedOne> registerService( TrackedOne trackedOne, String target) { Dictionary<String, Object> properties = new Hashtable<>(); properties.put("target", target); return _bundleContext.registerService( TrackedOne.class, trackedOne, properties); } private BundleContext _bundleContext; private ServiceTrackerMap<String, TrackedOne> _serviceTrackerMap; }