use of org.apache.aries.proxy.ProxyManager in project karaf by apache.
the class GuardProxyCatalogTest method testCreateProxy.
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object testCreateProxy(BundleContext bc, Class[] objectClasses, final Class[] proxyRegClasses, Object testService, final Map<ServiceReference, Object> serviceMap) throws Exception {
// A linked hash map to keep iteration order over the keys predictable
final LinkedHashMap<String, Class> objClsMap = new LinkedHashMap<>();
for (Class cls : objectClasses) {
objClsMap.put(cls.getName(), cls);
}
// A linked hash map to keep iteration order over the keys predictable
final LinkedHashMap<String, Class> proxyRegClsMap = new LinkedHashMap<>();
for (Class cls : proxyRegClasses) {
proxyRegClsMap.put(cls.getName(), cls);
}
// Create the object that is actually being tested here
GuardProxyCatalog gpc = new GuardProxyCatalog(bc);
// The service being proxied has these properties
long serviceID = Long.MAX_VALUE;
final Hashtable<String, Object> serviceProps = new Hashtable<>();
serviceProps.put(Constants.OBJECTCLASS, objClsMap.keySet().toArray(new String[] {}));
serviceProps.put(Constants.SERVICE_ID, serviceID);
// will be overwritten
serviceProps.put(GuardProxyCatalog.SERVICE_GUARD_ROLES_PROPERTY, Arrays.asList("everyone"));
serviceProps.put("bar", "foo");
// The mock bundle context for the bundle providing the service is set up here
BundleContext providerBC = EasyMock.createMock(BundleContext.class);
// These are the expected service properties of the proxy registration. Note the proxy marker...
final Hashtable<String, Object> expectedProxyProps = new Hashtable<>(serviceProps);
expectedProxyProps.put(GuardProxyCatalog.PROXY_SERVICE_KEY, Boolean.TRUE);
// This will check that the right proxy is being registered.
EasyMock.expect(providerBC.registerService(EasyMock.isA(String[].class), EasyMock.anyObject(), EasyMock.isA(Dictionary.class))).andAnswer((IAnswer) () -> {
if (!runningUnderCoverage) {
assertArrayEquals(proxyRegClsMap.keySet().toArray(new String[] {}), (String[]) EasyMock.getCurrentArguments()[0]);
Object svc = EasyMock.getCurrentArguments()[1];
assertTrue(svc instanceof ServiceFactory);
}
Dictionary<String, Object> props = (Dictionary<String, Object>) EasyMock.getCurrentArguments()[2];
for (String key : expectedProxyProps.keySet()) {
if (GuardProxyCatalog.SERVICE_GUARD_ROLES_PROPERTY.equals(key)) {
assertTrue("The roles property should have been overwritten", !Arrays.asList("everyone").equals(props.get(key)));
} else {
assertEquals(expectedProxyProps.get(key), props.get(key));
}
}
ServiceRegistration reg = EasyMock.createMock(ServiceRegistration.class);
ServiceReference sr = mockServiceReference(props);
EasyMock.expect(reg.getReference()).andReturn(sr).anyTimes();
reg.unregister();
EasyMock.expectLastCall().once();
EasyMock.replay(reg);
serviceMap.put(sr, EasyMock.getCurrentArguments()[1]);
return reg;
}).once();
EasyMock.expect(providerBC.getService(EasyMock.isA(ServiceReference.class))).andAnswer(() -> serviceMap.get(EasyMock.getCurrentArguments()[0])).anyTimes();
EasyMock.replay(providerBC);
// In some cases the proxy-creating code is looking for a classloader (e.g. when run through
// a coverage tool such as EclEmma). This will satisfy that.
BundleWiring bw = EasyMock.createMock(BundleWiring.class);
EasyMock.expect(bw.getClassLoader()).andReturn(getClass().getClassLoader()).anyTimes();
EasyMock.replay(bw);
// The mock bundle that provides the original service (and also the proxy is registered with this)
Bundle providerBundle = EasyMock.createNiceMock(Bundle.class);
EasyMock.expect(providerBundle.getBundleContext()).andReturn(providerBC).anyTimes();
EasyMock.expect(providerBundle.adapt(BundleWiring.class)).andReturn(bw).anyTimes();
EasyMock.replay(providerBundle);
ServiceReference sr = mockServiceReference(providerBundle, serviceProps);
// The mock bundle context for the client bundle
BundleContext clientBC = EasyMock.createMock(BundleContext.class);
EasyMock.expect(clientBC.getService(sr)).andReturn(testService).anyTimes();
EasyMock.replay(clientBC);
// The mock bundle that consumes the service
Bundle clientBundle = EasyMock.createNiceMock(Bundle.class);
EasyMock.expect(clientBundle.getBundleId()).andReturn(2999L).anyTimes();
EasyMock.expect(clientBundle.getBundleContext()).andReturn(clientBC).anyTimes();
EasyMock.expect(clientBundle.loadClass(EasyMock.isA(String.class))).andAnswer((IAnswer) () -> objClsMap.get(EasyMock.getCurrentArguments()[0])).anyTimes();
EasyMock.replay(clientBundle);
assertEquals("Precondition", 0, gpc.proxyMap.size());
assertEquals("Precondition", 0, gpc.createProxyQueue.size());
// Create the proxy for the service
gpc.proxyIfNotAlreadyProxied(sr);
assertEquals(1, gpc.proxyMap.size());
// The actual proxy creation is done asynchronously.
GuardProxyCatalog.ServiceRegistrationHolder holder = gpc.proxyMap.get(serviceID);
assertNull("The registration shouldn't have happened yet", holder.registration);
assertEquals(1, gpc.createProxyQueue.size());
// Mimic the thread that works the queue to create the proxy
GuardProxyCatalog.CreateProxyRunnable runnable = gpc.createProxyQueue.take();
ProxyManager pm = getProxyManager();
runnable.run(pm);
// The runnable should have put the actual registration in the holder
ServiceReference<?> proxySR = holder.registration.getReference();
for (String key : expectedProxyProps.keySet()) {
if (GuardProxyCatalog.SERVICE_GUARD_ROLES_PROPERTY.equals(key)) {
assertTrue("The roles property should have been overwritten", !Arrays.asList("everyone").equals(proxySR.getProperty(key)));
} else {
assertEquals(expectedProxyProps.get(key), proxySR.getProperty(key));
}
}
// Check that the proxy registration was done on the original provider bundle's context
EasyMock.verify(providerBC);
// Test that the actual proxy invokes the original service...
ServiceFactory proxyServiceSF = (ServiceFactory) serviceMap.get(proxySR);
Object proxyService = proxyServiceSF.getService(clientBundle, null);
assertNotSame("The proxy should not be the same object as the original service", testService, proxyService);
return proxyService;
}
use of org.apache.aries.proxy.ProxyManager in project karaf by apache.
the class GuardProxyCatalogTest method testProxyCreationThread.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testProxyCreationThread() throws Exception {
ProxyManager proxyManager = getProxyManager();
ConfigurationAdmin ca = EasyMock.createMock(ConfigurationAdmin.class);
EasyMock.expect(ca.listConfigurations(EasyMock.anyObject(String.class))).andReturn(null).anyTimes();
EasyMock.replay(ca);
ServiceReference pmSref = EasyMock.createMock(ServiceReference.class);
EasyMock.replay(pmSref);
ServiceReference pmSref2 = EasyMock.createMock(ServiceReference.class);
EasyMock.replay(pmSref2);
ServiceReference cmSref = EasyMock.createMock(ServiceReference.class);
EasyMock.replay(cmSref);
Bundle b = EasyMock.createMock(Bundle.class);
EasyMock.expect(b.getBundleId()).andReturn(23992734L).anyTimes();
EasyMock.replay(b);
BundleContext bc = EasyMock.createNiceMock(BundleContext.class);
EasyMock.expect(bc.getBundle()).andReturn(b).anyTimes();
EasyMock.expect(bc.createFilter(EasyMock.isA(String.class))).andAnswer(() -> FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0])).anyTimes();
final ServiceListener[] pmListenerHolder = new ServiceListener[1];
String pmFilter = "(&(objectClass=" + ProxyManager.class.getName() + ")" + "(!(" + GuardProxyCatalog.PROXY_SERVICE_KEY + "=*)))";
bc.addServiceListener(EasyMock.isA(ServiceListener.class), EasyMock.eq(pmFilter));
EasyMock.expectLastCall().andAnswer(() -> {
pmListenerHolder[0] = (ServiceListener) EasyMock.getCurrentArguments()[0];
return null;
}).anyTimes();
EasyMock.expect(bc.getServiceReferences(EasyMock.anyObject(String.class), EasyMock.contains(ConfigurationAdmin.class.getName()))).andReturn(new ServiceReference[] { cmSref }).anyTimes();
EasyMock.expect(bc.getService(pmSref)).andReturn(proxyManager).anyTimes();
EasyMock.expect(bc.getService(pmSref2)).andReturn(proxyManager).anyTimes();
EasyMock.expect(bc.getService(cmSref)).andReturn(ca).anyTimes();
EasyMock.replay(bc);
// This should put a ServiceListener in the pmListenerHolder, the ServiceTracker does that
GuardProxyCatalog gpc = new GuardProxyCatalog(bc);
// The service being proxied has these properties
final Hashtable<String, Object> serviceProps = new Hashtable<>();
serviceProps.put(Constants.OBJECTCLASS, new String[] { TestServiceAPI.class.getName() });
serviceProps.put(Constants.SERVICE_ID, 162L);
final Map<ServiceReference<?>, Object> serviceMap = new HashMap<>();
// The mock bundle context for the bundle providing the service is set up here
BundleContext providerBC = EasyMock.createMock(BundleContext.class);
// These are the expected service properties of the proxy registration. Note the proxy marker...
final Hashtable<String, Object> expectedProxyProps = new Hashtable<>(serviceProps);
expectedProxyProps.put(GuardProxyCatalog.PROXY_SERVICE_KEY, Boolean.TRUE);
EasyMock.expect(providerBC.registerService(EasyMock.isA(String[].class), EasyMock.anyObject(), EasyMock.isA(Dictionary.class))).andAnswer((IAnswer) () -> {
Dictionary<String, Object> props = (Dictionary<String, Object>) EasyMock.getCurrentArguments()[2];
ServiceRegistration reg = EasyMock.createMock(ServiceRegistration.class);
ServiceReference sr = mockServiceReference(props);
EasyMock.expect(reg.getReference()).andReturn(sr).anyTimes();
reg.unregister();
EasyMock.expectLastCall().once();
EasyMock.replay(reg);
serviceMap.put(sr, EasyMock.getCurrentArguments()[1]);
return reg;
}).once();
EasyMock.expect(providerBC.getService(EasyMock.isA(ServiceReference.class))).andAnswer(() -> serviceMap.get(EasyMock.getCurrentArguments()[0])).anyTimes();
EasyMock.replay(providerBC);
// In some cases the proxy-creating code is looking for a classloader (e.g. when run through
// a coverage tool such as EclEmma). This will satisfy that.
BundleWiring bw = EasyMock.createMock(BundleWiring.class);
EasyMock.expect(bw.getClassLoader()).andReturn(getClass().getClassLoader()).anyTimes();
EasyMock.replay(bw);
// The mock bundle that provides the original service (and also the proxy is registered with this)
Bundle providerBundle = EasyMock.createNiceMock(Bundle.class);
EasyMock.expect(providerBundle.getBundleContext()).andReturn(providerBC).anyTimes();
EasyMock.expect(providerBundle.adapt(BundleWiring.class)).andReturn(bw).anyTimes();
EasyMock.replay(providerBundle);
ServiceReference sr = mockServiceReference(providerBundle, serviceProps);
assertEquals("Precondition", 0, gpc.proxyMap.size());
assertEquals("Precondition", 0, gpc.createProxyQueue.size());
// Create the proxy for the service
gpc.proxyIfNotAlreadyProxied(sr);
assertEquals(1, gpc.proxyMap.size());
assertEquals(1, gpc.createProxyQueue.size());
// The actual proxy creation is done asynchronously.
GuardProxyCatalog.ServiceRegistrationHolder holder = gpc.proxyMap.get(162L);
assertNull("The registration shouldn't have happened yet", holder.registration);
assertEquals(1, gpc.createProxyQueue.size());
Thread[] tarray = new Thread[Thread.activeCount()];
Thread.enumerate(tarray);
for (Thread t : tarray) {
if (t != null) {
assertTrue(!GuardProxyCatalog.PROXY_CREATOR_THREAD_NAME.equals(t.getName()));
}
}
// make the proxy manager appear
pmListenerHolder[0].serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, pmSref));
// give the system some time to send the events...
Thread.sleep(400);
Thread ourThread = null;
Thread[] tarray2 = new Thread[Thread.activeCount()];
Thread.enumerate(tarray2);
for (Thread t : tarray2) {
if (t != null) {
if (t.getName().equals(GuardProxyCatalog.PROXY_CREATOR_THREAD_NAME)) {
ourThread = t;
}
}
}
assertNotNull(ourThread);
assertTrue(ourThread.isDaemon());
assertTrue(ourThread.isAlive());
assertNotNull(holder.registration);
assertEquals(0, gpc.createProxyQueue.size());
int numProxyThreads = 0;
pmListenerHolder[0].serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, pmSref2));
// give the system some time to send the events...
Thread.sleep(300);
Thread[] tarray3 = new Thread[Thread.activeCount()];
Thread.enumerate(tarray3);
for (Thread t : tarray3) {
if (t != null) {
if (t.getName().equals(GuardProxyCatalog.PROXY_CREATOR_THREAD_NAME)) {
numProxyThreads++;
}
}
}
assertEquals("Maximum 1 proxy thread, even if there is more than 1 proxy service", 1, numProxyThreads);
// Clean up thread
pmListenerHolder[0].serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, pmSref));
// Give the system some time to stop the threads...
Thread.sleep(300);
Thread[] tarray4 = new Thread[Thread.activeCount()];
Thread.enumerate(tarray4);
for (Thread t : tarray4) {
if (t != null) {
assertTrue(!GuardProxyCatalog.PROXY_CREATOR_THREAD_NAME.equals(t.getName()));
}
}
}
use of org.apache.aries.proxy.ProxyManager in project karaf by apache.
the class GuardProxyCatalogTest method testServiceFactoryBehaviour.
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testServiceFactoryBehaviour() throws Exception {
final Map<ServiceReference, Object> serviceMap = new HashMap<>();
TestServiceAPI testService = new TestService();
BundleContext bc = mockConfigAdminBundleContext();
GuardProxyCatalog gpc = new GuardProxyCatalog(bc);
// The service being proxied has these properties
long serviceID = 117L;
final Hashtable<String, Object> serviceProps = new Hashtable<>();
serviceProps.put(Constants.OBJECTCLASS, new String[] { TestServiceAPI.class.getName() });
serviceProps.put(Constants.SERVICE_ID, serviceID);
serviceProps.put("bar", 42L);
BundleContext providerBC = EasyMock.createMock(BundleContext.class);
EasyMock.expect(providerBC.registerService(EasyMock.isA(String[].class), EasyMock.anyObject(), EasyMock.isA(Dictionary.class))).andAnswer((IAnswer) () -> {
Dictionary<String, Object> props = (Dictionary<String, Object>) EasyMock.getCurrentArguments()[2];
ServiceRegistration reg = EasyMock.createMock(ServiceRegistration.class);
ServiceReference sr = mockServiceReference(props);
EasyMock.expect(reg.getReference()).andReturn(sr).anyTimes();
EasyMock.replay(reg);
serviceMap.put(sr, EasyMock.getCurrentArguments()[1]);
return reg;
}).once();
EasyMock.expect(providerBC.getService(EasyMock.isA(ServiceReference.class))).andAnswer(() -> serviceMap.get(EasyMock.getCurrentArguments()[0])).anyTimes();
EasyMock.replay(providerBC);
// In some cases the proxy-creating code is looking for a classloader (e.g. when run through
// a coverage tool such as EclEmma). This will satisfy that.
BundleWiring bw = EasyMock.createMock(BundleWiring.class);
EasyMock.expect(bw.getClassLoader()).andReturn(getClass().getClassLoader()).anyTimes();
EasyMock.replay(bw);
// The mock bundle that provides the original service (and also the proxy is registered with this)
Bundle providerBundle = EasyMock.createNiceMock(Bundle.class);
EasyMock.expect(providerBundle.getBundleContext()).andReturn(providerBC).anyTimes();
EasyMock.expect(providerBundle.adapt(BundleWiring.class)).andReturn(bw).anyTimes();
EasyMock.replay(providerBundle);
ServiceReference sr = mockServiceReference(providerBundle, serviceProps);
// The mock bundle context for the client bundle
BundleContext clientBC = EasyMock.createMock(BundleContext.class);
EasyMock.expect(clientBC.getService(sr)).andReturn(testService).anyTimes();
EasyMock.replay(clientBC);
// The mock bundle that consumes the service
Bundle clientBundle = EasyMock.createNiceMock(Bundle.class);
EasyMock.expect(clientBundle.getBundleContext()).andReturn(clientBC).anyTimes();
EasyMock.replay(clientBundle);
gpc.proxyIfNotAlreadyProxied(sr);
// The actual proxy creation is done asynchronously.
GuardProxyCatalog.ServiceRegistrationHolder holder = gpc.proxyMap.get(serviceID);
// Mimic the thread that works the queue to create the proxy
GuardProxyCatalog.CreateProxyRunnable runnable = gpc.createProxyQueue.take();
assertEquals(117L, runnable.getOriginalServiceID());
ProxyManager pm = getProxyManager();
runnable.run(pm);
// The runnable should have put the actual registration in the holder
ServiceReference<?> proxySR = holder.registration.getReference();
// Check that the proxy registration was done on the original provider bundle's context
EasyMock.verify(providerBC);
// Test that the actual proxy invokes the original service...
ServiceFactory proxyServiceSF = (ServiceFactory) serviceMap.get(proxySR);
TestServiceAPI proxyService = (TestServiceAPI) proxyServiceSF.getService(clientBundle, null);
assertNotSame("The proxy should not be the same object as the original service", testService, proxyService);
assertEquals("Doing it", proxyService.doit());
EasyMock.reset(clientBC);
EasyMock.expect(clientBC.ungetService(sr)).andReturn(true).once();
EasyMock.replay(clientBC);
proxyServiceSF.ungetService(clientBundle, null, proxyService);
EasyMock.verify(clientBC);
}
use of org.apache.aries.proxy.ProxyManager in project karaf by apache.
the class Activator method doStart.
@Override
protected void doStart() throws Exception {
ProxyManager proxyManager = getTrackedService(ProxyManager.class);
register(InitialContextFactory.class, new KarafInitialContextFactory());
JndiServiceImpl service = new JndiServiceImpl();
service.setBundleContext(bundleContext);
service.setProxyManager(proxyManager);
Hashtable<String, String> props = new Hashtable<>();
// bind the JNDI service itself in the JNDI context
props.put("osgi.jndi.service.name", "jndi");
register(JndiService.class, service, props);
JndiMBeanImpl mbean = new JndiMBeanImpl();
mbean.setJndiService(service);
registerMBean(mbean, "type=jndi");
}
use of org.apache.aries.proxy.ProxyManager in project aries by apache.
the class ServiceHelper method proxyPrivileged.
private static Object proxyPrivileged(String interface1, String filter, boolean dynamicRebind, BundleContext ctx, ServicePair pair, int timeout) {
String[] interfaces = null;
if (interface1 != null) {
interfaces = new String[] { interface1 };
} else {
interfaces = (String[]) pair.ref.getProperty(Constants.OBJECTCLASS);
}
List<Class<?>> clazz = new ArrayList<Class<?>>(interfaces.length);
// We load the interface classes the service is registered under using the defining bundle.
// This is ok because the service must be able to see the classes to be registered using them.
// We then check to see if isAssignableTo on the reference works for the owning bundle and
// the interface name and only use the interface if true is returned there.
// This might seem odd, but equinox and felix return true for isAssignableTo if the
// Bundle provided does not import the package. This is under the assumption the
// caller will then use reflection. The upshot of doing it this way is that a utility
// bundle can be created which centralizes JNDI lookups, but the service will be used
// by another bundle. It is true that class space consistency is less safe, but we
// are enabling a slightly odd use case anyway.
// August 13th 2013: We've found valid use cases in which a Bundle is exporting
// services that the Bundle itself cannot load. We deal with this rare case by
// noting the classes that we failed to load. If as a result we have no classes
// to proxy, we try those classes again but instead pull the Class objects off
// the service rather than from the bundle exporting that service.
Bundle serviceProviderBundle = pair.ref.getBundle();
Bundle owningBundle = ctx.getBundle();
ProxyManager proxyManager = Activator.getProxyManager();
Collection<String> classesNotFound = new ArrayList<String>();
for (String interfaceName : interfaces) {
try {
Class<?> potentialClass = serviceProviderBundle.loadClass(interfaceName);
if (pair.ref.isAssignableTo(owningBundle, interfaceName)) {
clazz.add(potentialClass);
}
} catch (ClassNotFoundException e) {
classesNotFound.add(interfaceName);
}
}
if (clazz.isEmpty() && !classesNotFound.isEmpty()) {
Class<?>[] ifacesOnService = ctx.getService(pair.ref).getClass().getInterfaces();
for (String interfaceName : classesNotFound) {
Class<?> thisClass = null;
for (Class<?> c : getAllInterfaces(ifacesOnService)) {
if (c.getName().equals(interfaceName)) {
thisClass = c;
break;
}
}
if (thisClass != null) {
if (pair.ref.isAssignableTo(owningBundle, interfaceName)) {
clazz.add(thisClass);
}
}
}
}
if (clazz.isEmpty()) {
throw new IllegalArgumentException(Arrays.asList(interfaces).toString());
}
Callable<Object> ih = new JNDIServiceDamper(ctx, interface1, filter, pair, dynamicRebind, timeout);
try {
return proxyManager.createDelegatingProxy(serviceProviderBundle, clazz, ih, null);
} catch (UnableToProxyException e) {
throw new IllegalArgumentException(e);
} catch (RuntimeException e) {
throw new IllegalArgumentException(MESSAGES.getMessage("unable.to.create.proxy", pair.ref), e);
}
}
Aggregations