/* * 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.framework; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.Observable; import java.util.Observer; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; import org.apache.felix.framework.ServiceRegistrationImpl.ServiceReferenceImpl; import org.apache.felix.framework.ServiceRegistry.ServiceHolder; import org.apache.felix.framework.ServiceRegistry.UsageCount; import org.easymock.MockControl; import org.mockito.AdditionalAnswers; import org.mockito.InOrder; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceException; import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.hooks.service.EventHook; import org.osgi.framework.hooks.service.FindHook; import org.osgi.framework.hooks.service.ListenerHook; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; public class ServiceRegistryTest extends TestCase { public void testRegisterEventHookService() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); EventHook hook = new EventHook() { @Override public void event(ServiceEvent event, Collection contexts) { } }; assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {EventHook.class.getName()}, hook, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); assertTrue(sr.getHookRegistry().getHooks(EventHook.class).iterator().next() instanceof ServiceReference); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterEventHookServiceFactory() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class); sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {EventHook.class.getName()}, sf, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterFindHookService() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); FindHook hook = new FindHook() { @Override public void find(BundleContext context, String name, String filter, boolean allServices, Collection references) { } }; assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {FindHook.class.getName()}, hook, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterFindHookServiceFactory() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class); sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {FindHook.class.getName()}, sf, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterListenerHookService() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); ListenerHook hook = new ListenerHook() { @Override public void added(Collection listeners) { } @Override public void removed(Collection listener) { } }; assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {ListenerHook.class.getName()}, hook, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterListenerHookServiceFactory() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class); sfControl.replay(); ServiceFactory sf = (ServiceFactory) sfControl.getMock(); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {ListenerHook.class.getName()}, sf, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(sf, ((ServiceRegistrationImpl) reg).getService()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterCombinedService() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); class CombinedService implements ListenerHook, FindHook, EventHook, Runnable { @Override public void added(Collection listeners) { } @Override public void removed(Collection listener) { } @Override public void find(BundleContext context, String name, String filter, boolean allServices, Collection references) { } @Override public void event(ServiceEvent event, Collection contexts) { } @Override public void run() { } } CombinedService hook = new CombinedService(); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] { Runnable.class.getName(), ListenerHook.class.getName(), FindHook.class.getName(), EventHook.class.getName()}, hook, new Hashtable()); assertEquals(1, sr.getHookRegistry().getHooks(ListenerHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(ListenerHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); assertEquals(1, sr.getHookRegistry().getHooks(EventHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(EventHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); assertEquals(1, sr.getHookRegistry().getHooks(FindHook.class).size()); assertSame(reg.getReference(), sr.getHookRegistry().getHooks(FindHook.class).iterator().next()); assertSame(hook, ((ServiceRegistrationImpl) reg).getService()); sr.unregisterService(b, reg); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Should be no hooks left after unregistration", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } public void testRegisterPlainService() { MockControl control = MockControl.createNiceControl(Bundle.class); Bundle b = (Bundle) control.getMock(); control.replay(); MockControl controlContext = MockControl.createNiceControl(BundleContext.class); BundleContext c = (BundleContext) controlContext.getMock(); controlContext.expectAndReturn(c.getBundle(), b); controlContext.replay(); ServiceRegistry sr = new ServiceRegistry(new Logger(), null); String svcObj = "hello"; assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Precondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); ServiceRegistration reg = sr.registerService(c.getBundle(), new String [] {String.class.getName()}, svcObj, new Hashtable()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Postcondition failed", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); sr.unregisterService(b, reg); assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(EventHook.class).size()); assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(FindHook.class).size()); assertEquals("Unregistration should have no effect", 0, sr.getHookRegistry().getHooks(ListenerHook.class).size()); } @SuppressWarnings("unchecked") public void testGetService() { ServiceRegistry sr = new ServiceRegistry(null, null); String svc = "foo"; Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(true); Mockito.when(reg.getService(b)).thenReturn(svc); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); assertSame(svc, sr.getService(b, ref, false)); } @SuppressWarnings("unchecked") public void testGetServiceHolderAwait() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); final String svc = "test"; Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(true); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); UsageCount uc = sr.obtainUsageCount(b, ref, null, false); // Set an empty Service Holder so we can test that it waits. final ServiceHolder sh = new ServiceHolder(); uc.m_svcHolderRef.set(sh); final StringBuffer sb = new StringBuffer(); final AtomicBoolean threadException = new AtomicBoolean(false); Thread t = new Thread() { @Override public void run() { try { Thread.sleep(250); } catch (InterruptedException e) {} sh.m_service = svc; if (sb.length() > 0) { // Should not have put anything in SB until countDown() was called... threadException.set(true); } sh.m_latch.countDown(); } }; assertFalse(t.isInterrupted()); t.start(); Object actualSvc = sr.getService(b, ref, false); sb.append(actualSvc); t.join(); assertFalse("This thread did not wait until the latch was count down", threadException.get()); assertSame(svc, actualSvc); } @SuppressWarnings("unchecked") public void testGetServicePrototype() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); String svc = "xyz"; Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(true); Mockito.when(reg.getService(b)).thenReturn(svc); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); assertSame(svc, sr.getService(b, ref, true)); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); UsageCount[] uca = inUseMap.get(b); assertEquals(1, uca.length); assertEquals(1, uca[0].m_serviceObjectsCount.get()); sr.getService(b, ref, true); assertEquals(2, uca[0].m_serviceObjectsCount.get()); } @SuppressWarnings("unchecked") public void testGetServiceThreadMarking() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); sr.getService(b, ref, false); InOrder inOrder = Mockito.inOrder(reg); inOrder.verify(reg, Mockito.times(1)).currentThreadMarked(); inOrder.verify(reg, Mockito.times(1)).markCurrentThread(); inOrder.verify(reg, Mockito.times(1)).unmarkCurrentThread(); } @SuppressWarnings("unchecked") public void testGetServiceThreadMarking2() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); String svc = "bar"; Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = (ServiceRegistrationImpl) sr.registerService( b, new String [] {String.class.getName()}, svc, null); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); reg.markCurrentThread(); try { sr.getService(b, ref, false); fail("Should have thrown an exception to signal reentrant behaviour"); } catch (ServiceException se) { assertEquals(ServiceException.FACTORY_ERROR, se.getType()); } } @SuppressWarnings("unchecked") public void testUngetService() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); UsageCount uc = new UsageCount(ref, false); uc.m_svcHolderRef.set(new ServiceHolder()); inUseMap.put(b, new UsageCount[] {uc}); assertFalse(sr.ungetService(b, ref, null)); assertNull(uc.m_svcHolderRef.get()); } @SuppressWarnings("unchecked") public void testUngetService2() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); UsageCount uc = new UsageCount(ref, false); ServiceHolder sh = new ServiceHolder(); Object svc = new Object(); sh.m_service = svc; uc.m_svcHolderRef.set(sh); uc.m_count.incrementAndGet(); Mockito.verify(reg, Mockito.never()). ungetService(Mockito.isA(Bundle.class), Mockito.any()); inUseMap.put(b, new UsageCount[] {uc}); assertTrue(sr.ungetService(b, ref, null)); assertNull(uc.m_svcHolderRef.get()); Mockito.verify(reg, Mockito.times(1)). ungetService(Mockito.isA(Bundle.class), Mockito.eq(svc)); } @SuppressWarnings("unchecked") public void testUngetService3() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(true); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); UsageCount uc = new UsageCount(ref, false); uc.m_svcHolderRef.set(new ServiceHolder()); uc.m_count.set(2); inUseMap.put(b, new UsageCount[] {uc}); assertTrue(sr.ungetService(b, ref, null)); assertNotNull(uc.m_svcHolderRef.get()); assertNotNull(inUseMap.get(b)); Mockito.verify(reg, Mockito.never()). ungetService(Mockito.isA(Bundle.class), Mockito.any()); } @SuppressWarnings("unchecked") public void testUngetService4() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(false); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); UsageCount uc = new UsageCount(ref, false); uc.m_svcHolderRef.set(new ServiceHolder()); uc.m_count.set(2); inUseMap.put(b, new UsageCount[] {uc}); assertTrue(sr.ungetService(b, ref, null)); assertNull(uc.m_svcHolderRef.get()); Mockito.verify(reg, Mockito.never()). ungetService(Mockito.isA(Bundle.class), Mockito.any()); } @SuppressWarnings("unchecked") public void testUngetService5() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.doThrow(new RuntimeException("Test!")).when(reg). ungetService(Mockito.isA(Bundle.class), Mockito.any()); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); String svc = "myService"; UsageCount uc = new UsageCount(ref, false); ServiceHolder sh = new ServiceHolder(); sh.m_service = svc; sh.m_latch.countDown(); uc.m_svcHolderRef.set(sh); uc.m_count.set(1); inUseMap.put(b, new UsageCount[] {uc}); try { assertTrue(sr.ungetService(b, ref, null)); fail("Should have propagated the runtime exception"); } catch (RuntimeException re) { assertEquals("Test!", re.getMessage()); } assertNull(uc.m_svcHolderRef.get()); Mockito.verify(reg, Mockito.times(1)).ungetService(b, svc); } public void testUngetServiceThreadMarking() { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); assertFalse("There is no usage count, so this method should return false", sr.ungetService(b, ref, null)); InOrder inOrder = Mockito.inOrder(reg); inOrder.verify(reg, Mockito.times(1)).currentThreadMarked(); inOrder.verify(reg, Mockito.times(1)).markCurrentThread(); inOrder.verify(reg, Mockito.times(1)).unmarkCurrentThread(); } public void testUngetServiceThreadMarking2() { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.currentThreadMarked()).thenReturn(true); ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); try { sr.ungetService(b, ref, null); fail("The thread should be observed as marked and hence throw an exception"); } catch (IllegalStateException ise) { // good } } public void testObtainUsageCount() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); assertEquals("Precondition", 0, inUseMap.size()); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = sr.obtainUsageCount(b, ref, null, false); assertEquals(1, inUseMap.size()); assertEquals(1, inUseMap.get(b).length); assertSame(uc, inUseMap.get(b)[0]); assertSame(ref, uc.m_ref); assertFalse(uc.m_prototype); UsageCount uc2 = sr.obtainUsageCount(b, ref, null, false); assertSame(uc, uc2); ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); UsageCount uc3 = sr.obtainUsageCount(b, ref2, null, false); assertNotSame(uc3, uc2); assertSame(ref2, uc3.m_ref); } public void testObtainUsageCountPrototype() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = sr.obtainUsageCount(b, ref, null, true); assertEquals(1, inUseMap.size()); assertEquals(1, inUseMap.values().iterator().next().length); ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); UsageCount uc2 = sr.obtainUsageCount(b, ref2, null, true); assertEquals(1, inUseMap.size()); assertEquals(2, inUseMap.values().iterator().next().length); List<UsageCount> ucl = Arrays.asList(inUseMap.get(b)); assertTrue(ucl.contains(uc)); assertTrue(ucl.contains(uc2)); } public void testObtainUsageCountPrototypeUnknownLookup() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, true); ServiceHolder sh = new ServiceHolder(); String svc = "foobar"; sh.m_service = svc; uc.m_svcHolderRef.set(sh); inUseMap.put(b, new UsageCount[] {uc}); assertNull(sr.obtainUsageCount(b, Mockito.mock(ServiceReference.class), null, null)); UsageCount uc2 = sr.obtainUsageCount(b, ref, svc, null); assertSame(uc, uc2); } public void testObtainUsageCountPrototypeUnknownLookup2() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, false); inUseMap.put(b, new UsageCount[] {uc}); assertNull(sr.obtainUsageCount(b, Mockito.mock(ServiceReference.class), null, null)); UsageCount uc2 = sr.obtainUsageCount(b, ref, null, null); assertSame(uc, uc2); } @SuppressWarnings("unchecked") public void testObtainUsageCountRetry1() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle b = Mockito.mock(Bundle.class); final ConcurrentMap<Bundle, UsageCount[]> orgInUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); ConcurrentMap<Bundle, UsageCount[]> inUseMap = Mockito.mock(ConcurrentMap.class, AdditionalAnswers.delegatesTo(orgInUseMap)); Mockito.doAnswer(new Answer<UsageCount[]>() { @Override public UsageCount[] answer(InvocationOnMock invocation) throws Throwable { // This mimicks another thread putting another UsageCount in concurrently // The putIfAbsent() will fail and it has to retry UsageCount uc = new UsageCount(Mockito.mock(ServiceReference.class), false); UsageCount[] uca = new UsageCount[] {uc}; orgInUseMap.put(b, uca); return uca; } }).when(inUseMap).putIfAbsent(Mockito.any(Bundle.class), Mockito.any(UsageCount[].class)); setPrivateField(sr, "m_inUseMap", inUseMap); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); assertEquals(0, orgInUseMap.size()); UsageCount uc = sr.obtainUsageCount(b, ref, null, false); assertEquals(1, orgInUseMap.size()); assertEquals(2, orgInUseMap.get(b).length); assertSame(ref, uc.m_ref); assertFalse(uc.m_prototype); List<UsageCount> l = new ArrayList<UsageCount>(Arrays.asList(orgInUseMap.get(b))); l.remove(uc); assertEquals("There should be one UsageCount left", 1, l.size()); assertNotSame(ref, l.get(0).m_ref); } @SuppressWarnings("unchecked") public void testObtainUsageCountRetry2() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle b = Mockito.mock(Bundle.class); final ConcurrentMap<Bundle, UsageCount[]> orgInUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); orgInUseMap.put(b, new UsageCount[] {new UsageCount(Mockito.mock(ServiceReference.class), false)}); ConcurrentMap<Bundle, UsageCount[]> inUseMap = Mockito.mock(ConcurrentMap.class, AdditionalAnswers.delegatesTo(orgInUseMap)); Mockito.doAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { orgInUseMap.remove(b); return false; } }).when(inUseMap).replace(Mockito.any(Bundle.class), Mockito.any(UsageCount[].class), Mockito.any(UsageCount[].class)); setPrivateField(sr, "m_inUseMap", inUseMap); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); assertEquals("Precondition", 1, inUseMap.size()); assertEquals("Precondition", 1, inUseMap.values().iterator().next().length); assertNotSame("Precondition", ref, inUseMap.get(b)[0].m_ref); sr.obtainUsageCount(b, ref, null, false); assertEquals(1, inUseMap.size()); assertEquals(1, inUseMap.values().iterator().next().length); assertSame("The old usage count should have been removed by the mock and this one should have been added", ref, inUseMap.get(b)[0].m_ref); } public void testFlushUsageCount() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, false); ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); UsageCount uc2 = new UsageCount(ref2, true); inUseMap.put(b, new UsageCount[] {uc, uc2}); assertEquals("Precondition", 1, inUseMap.size()); assertEquals("Precondition", 2, inUseMap.values().iterator().next().length); sr.flushUsageCount(b, ref, uc); assertEquals(1, inUseMap.size()); assertEquals(1, inUseMap.values().iterator().next().length); assertSame(uc2, inUseMap.values().iterator().next()[0]); sr.flushUsageCount(b, ref2, uc2); assertEquals(0, inUseMap.size()); } public void testFlushUsageCountNullRef() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); Bundle b2 = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, false); ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); UsageCount uc2 = new UsageCount(ref2, true); ServiceReference<?> ref3 = Mockito.mock(ServiceReference.class); UsageCount uc3 = new UsageCount(ref3, true); inUseMap.put(b, new UsageCount[] {uc2, uc}); inUseMap.put(b2, new UsageCount[] {uc3}); assertEquals("Precondition", 2, inUseMap.size()); sr.flushUsageCount(b, null, uc); assertEquals(2, inUseMap.size()); sr.flushUsageCount(b, null, uc2); assertEquals(1, inUseMap.size()); } public void testFlushUsageCountAlienObject() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, false); inUseMap.put(b, new UsageCount[] {uc}); assertEquals("Precondition", 1, inUseMap.size()); assertEquals("Precondition", 1, inUseMap.values().iterator().next().length); UsageCount uc2 = new UsageCount(Mockito.mock(ServiceReference.class), false); sr.flushUsageCount(b, ref, uc2); assertEquals("Should be no changes", 1, inUseMap.size()); assertEquals("Should be no changes", 1, inUseMap.values().iterator().next().length); } public void testFlushUsageCountNull() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); @SuppressWarnings("unchecked") ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); Bundle b = Mockito.mock(Bundle.class); Bundle b2 = Mockito.mock(Bundle.class); ServiceReference<?> ref = Mockito.mock(ServiceReference.class); UsageCount uc = new UsageCount(ref, false); ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); UsageCount uc2 = new UsageCount(ref2, true); ServiceReference<?> ref3 = Mockito.mock(ServiceReference.class); UsageCount uc3 = new UsageCount(ref3, true); inUseMap.put(b, new UsageCount[] {uc2, uc}); inUseMap.put(b2, new UsageCount[] {uc3}); assertEquals("Precondition", 2, inUseMap.size()); sr.flushUsageCount(b, ref, null); assertEquals(2, inUseMap.size()); sr.flushUsageCount(b, ref2, null); assertEquals(1, inUseMap.size()); } @SuppressWarnings("unchecked") public void testFlushUsageCountRetry() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle b = Mockito.mock(Bundle.class); final ServiceReference<?> ref = Mockito.mock(ServiceReference.class); final UsageCount uc = new UsageCount(ref, false); final ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); final UsageCount uc2 = new UsageCount(ref2, false); final ConcurrentMap<Bundle, UsageCount[]> orgInUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = Mockito.mock(ConcurrentMap.class, AdditionalAnswers.delegatesTo(orgInUseMap)); Mockito.doAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { inUseMap.put(b, new UsageCount[] {uc}); return false; } }).when(inUseMap).replace(Mockito.isA(Bundle.class), Mockito.isA(UsageCount[].class), Mockito.isA(UsageCount[].class)); setPrivateField(sr, "m_inUseMap", inUseMap); inUseMap.put(b, new UsageCount[] {uc, uc2}); sr.flushUsageCount(b, null, uc); assertNull("A 'concurrent' process has removed uc2 as well, " + "so the entry for 'b' should have been removed", inUseMap.get(b)); } public void testFlushUsageCountRetry2() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle b = Mockito.mock(Bundle.class); final ServiceReference<?> ref = Mockito.mock(ServiceReference.class); final UsageCount uc = new UsageCount(ref, false); final ServiceReference<?> ref2 = Mockito.mock(ServiceReference.class); final UsageCount uc2 = new UsageCount(ref2, false); final ConcurrentMap<Bundle, UsageCount[]> orgInUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); final ConcurrentMap<Bundle, UsageCount[]> inUseMap = Mockito.mock(ConcurrentMap.class, AdditionalAnswers.delegatesTo(orgInUseMap)); Mockito.doAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { inUseMap.put(b, new UsageCount[] {uc, uc2}); return false; } }).when(inUseMap).remove(Mockito.isA(Bundle.class), Mockito.isA(UsageCount[].class)); setPrivateField(sr, "m_inUseMap", inUseMap); inUseMap.put(b, new UsageCount[] {uc}); sr.flushUsageCount(b, null, uc); assertEquals(1, inUseMap.get(b).length); assertSame(uc2, inUseMap.get(b)[0]); } public void testGetUngetServiceFactory() throws Exception { final ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle regBundle = Mockito.mock(Bundle.class); final ServiceRegistration<?> reg = sr.registerService(regBundle, new String[] {Observer.class.getName()}, new ServiceFactory<Observer>() { final class ObserverImpl implements Observer { private final AtomicInteger counter = new AtomicInteger(); public volatile boolean active = true; @Override public void update(Observable o, Object arg) { counter.incrementAndGet(); if ( !active ) { throw new IllegalArgumentException("Iteration:" + counter.get()); } } }; @Override public Observer getService(Bundle bundle, ServiceRegistration<Observer> registration) { return new ObserverImpl(); } @Override public void ungetService(Bundle bundle, ServiceRegistration<Observer> registration, Observer service) { ((ObserverImpl)service).active = false; } }, null); final Bundle clientBundle = Mockito.mock(Bundle.class); Mockito.when(clientBundle.getBundleId()).thenReturn(42L); // check simple get/unget final Object obj = sr.getService(clientBundle, reg.getReference(), false); assertNotNull(obj); assertTrue(obj instanceof Observer); ((Observer)obj).update(null, null); sr.ungetService(clientBundle, reg.getReference(), null); try { ((Observer)obj).update(null, null); fail(); } catch ( final IllegalArgumentException iae) { // expected } // start three threads final int MAX_THREADS = 3; final int MAX_LOOPS = 50000; final CountDownLatch latch = new CountDownLatch(MAX_THREADS); final Thread[] threads = new Thread[MAX_THREADS]; final List<Exception> exceptions = Collections.synchronizedList(new ArrayList<Exception>()); for(int i=0; i<MAX_THREADS; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { try { Thread.currentThread().sleep(50); } catch (InterruptedException e1) { // ignore } for(int i=0; i < MAX_LOOPS; i++) { try { final Object obj = sr.getService(clientBundle, reg.getReference(), false); ((Observer)obj).update(null, null); sr.ungetService(clientBundle, reg.getReference(), null); } catch ( final Exception e) { exceptions.add(e); } } latch.countDown(); } }); } for(int i=0; i<MAX_THREADS; i++) { threads[i].start(); } latch.await(); List<String> counterValues = new ArrayList<String>(); for (Exception ex : exceptions) { counterValues.add(ex.getMessage()); } assertTrue("" + counterValues, exceptions.isEmpty()); } public void testUsageCountCleanup() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle regBundle = Mockito.mock(Bundle.class); ServiceRegistration<?> reg = sr.registerService( regBundle, new String [] {String.class.getName()}, "hi", null); final Bundle clientBundle = Mockito.mock(Bundle.class); Mockito.when(clientBundle.getBundleId()).thenReturn(327L); assertEquals("hi", sr.getService(clientBundle, reg.getReference(), false)); sr.ungetService(clientBundle, reg.getReference(), null); ConcurrentMap<Bundle, UsageCount[]> inUseMap = (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap"); sr.unregisterService(regBundle, reg); assertEquals(0, inUseMap.size()); } @SuppressWarnings("unchecked") public void testGetServiceThrowsException() throws Exception { final ServiceRegistry sr = new ServiceRegistry(null, null); final Bundle b = Mockito.mock(Bundle.class); ServiceRegistrationImpl reg = Mockito.mock(ServiceRegistrationImpl.class); Mockito.when(reg.isValid()).thenReturn(true); Mockito.when(reg.getService(b)).thenAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Thread.sleep(500); throw new Exception("boo!"); } }); final ServiceReferenceImpl ref = Mockito.mock(ServiceReferenceImpl.class); Mockito.when(ref.getRegistration()).thenReturn(reg); final StringBuffer sb = new StringBuffer(); Thread t = new Thread() { @Override public void run() { try { assertEquals("Should not yet have given the service to the other thread", "", sb.toString()); sr.getService(b, ref, false); } catch (Exception e) { // We expect an exception here. } } }; t.start(); // Wait until the other thread has called getService(); Thread.sleep(250); // This thread has waited long enough for the other thread to call getService() // however the actual getService() call blocks long enough for this one to then // concurrently call getService() while the other thread is in getService() of the // factory. This thread will then end up in m_latch.await(). // The factory implementation of the other thread then throws an exception. This test // ultimately checks that this thread here is not stuck waiting forwever. assertNull(sr.getService(b, ref, false)); sb.append("Obtained service"); } public void testUsingBundlesWithoutZeroCounts() throws Exception { ServiceRegistry sr = new ServiceRegistry(null, null); Bundle regBundle = Mockito.mock(Bundle.class); ServiceRegistration reg = sr.registerService( regBundle, new String [] {String.class.getName()}, "hi", null); @SuppressWarnings("unchecked") ServiceReference<String> ref = reg.getReference(); final Bundle clientBundle = Mockito.mock(Bundle.class); Mockito.when(clientBundle.getBundleId()).thenReturn(42L); assertThat(sr.getService(clientBundle, ref, false), is("hi")); final Bundle clientBundle2 = Mockito.mock(Bundle.class); Mockito.when(clientBundle.getBundleId()).thenReturn(327L); assertThat(sr.getService(clientBundle2, ref, false), is("hi")); assertThat(sr.ungetService(clientBundle, reg.getReference(), null), is(true)); assertThat(sr.getUsingBundles(reg.getReference()), is(new Bundle[]{clientBundle2})); } private Object getPrivateField(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException { Field f = ServiceRegistry.class.getDeclaredField(fieldName); f.setAccessible(true); return f.get(obj); } private void setPrivateField(ServiceRegistry obj, String fieldName, Object val) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field f = ServiceRegistry.class.getDeclaredField(fieldName); f.setAccessible(true); f.set(obj, val); } }