/** * 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.ServiceTracker; import com.liferay.registry.ServiceTrackerFieldUpdaterCustomizer; import com.liferay.registry.internal.RegistryImpl; import java.io.Closeable; import java.lang.reflect.Field; import java.util.Hashtable; 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 Shuyang Zhou */ @RunWith(Arquillian.class) public class ServiceTrackerFieldUpdaterCustomizerTest { @Before public void setUp() throws BundleException { _bundle.start(); RegistryUtil.setRegistry(new RegistryImpl(_bundleContext)); } @After public void tearDown() throws BundleException { _bundle.stop(); } @Test public void testFieldUpdate() throws Exception { try (TestServiceUsage testServiceUsage = new StaticTestServiceUsage()) { doTestFieldUpdate(testServiceUsage, _defaultTestService); } try (TestServiceUsage testServiceUsage = new NonStaticTestServiceUsage()) { doTestFieldUpdate(testServiceUsage, null); } } @Test public void testWrongDeclaration() throws NoSuchFieldException { Field field = ServiceTrackerFieldUpdaterCustomizerTest.class.getDeclaredField( "_bundle"); try { new ServiceTrackerFieldUpdaterCustomizer(field, this, null); Assert.fail(); } catch (IllegalArgumentException iae) { Assert.assertEquals(field + " is not volatile", iae.getMessage()); } } protected void doTestFieldUpdate( TestServiceUsage testServiceUsage, TestService defaultTestService) { // Starting with null Assert.assertNull(testServiceUsage.getTestService()); // Update field to use testService1 TestService testService1 = new TestService1(); ServiceRegistration<TestService> serviceRegistration1 = _registerService(testService1, 0); Assert.assertSame(testService1, testServiceUsage.getTestService()); // Update field to use testService2, by out ranking testService1 TestService testService2 = new TestService2(); ServiceRegistration<TestService> serviceRegistration2 = _registerService(testService2, 1); Assert.assertSame(testService2, testServiceUsage.getTestService()); // Upgrade testService1 ranking to suppress testService2 Hashtable<String, Object> hashtable = new Hashtable<>(); hashtable.put("service.ranking", "2"); serviceRegistration1.setProperties(hashtable); Assert.assertSame(testService1, testServiceUsage.getTestService()); // Unregister testService1 and testService2 to fallback to default serviceRegistration1.unregister(); serviceRegistration2.unregister(); Assert.assertSame( defaultTestService, testServiceUsage.getTestService()); } private ServiceRegistration<TestService> _registerService( TestService testService, int ranking) { Hashtable<String, Object> hashtable = new Hashtable<>(); if (ranking != 0) { hashtable.put("service.ranking", ranking); } return _bundleContext.registerService( TestService.class, testService, hashtable); } private static final TestService _defaultTestService = new TestServiceDefault(); @ArquillianResource private Bundle _bundle; @ArquillianResource private BundleContext _bundleContext; private static class NonStaticTestServiceUsage implements TestServiceUsage { @Override public void close() { _serviceTracker.close(); } public TestService getTestService() { return _testService; } private NonStaticTestServiceUsage() throws NoSuchFieldException { Registry registry = RegistryUtil.getRegistry(); Field field = NonStaticTestServiceUsage.class.getDeclaredField( "_testService"); field.setAccessible(true); _serviceTracker = registry.trackServices( TestService.class, new ServiceTrackerFieldUpdaterCustomizer <TestService, TestService>(field, this, null)); _serviceTracker.open(); } private final ServiceTracker<TestService, TestService> _serviceTracker; private volatile TestService _testService; } private static class StaticTestServiceUsage implements TestServiceUsage { @Override public void close() { _serviceTracker.close(); } public TestService getTestService() { return _testService; } private static final ServiceTracker<TestService, TestService> _serviceTracker; private static volatile TestService _testService; static { Registry registry = RegistryUtil.getRegistry(); try { Field field = StaticTestServiceUsage.class.getDeclaredField( "_testService"); field.setAccessible(true); _serviceTracker = registry.trackServices( TestService.class, new ServiceTrackerFieldUpdaterCustomizer <TestService, TestService>( field, null, _defaultTestService)); _serviceTracker.open(); } catch (NoSuchFieldException nsfe) { throw new ExceptionInInitializerError(nsfe); } } } private static class TestService1 implements TestService { } private static class TestService2 implements TestService { } private static class TestServiceDefault implements TestService { } private interface TestService { } private interface TestServiceUsage extends Closeable { public TestService getTestService(); } }