package org.camunda.bpm.extension.osgi.eventing.impl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import org.camunda.bpm.extension.osgi.eventing.api.OSGiEventBridgeActivator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.event.EventAdmin; /** * This InvocationHandler sends OSGi events only in case that the required * services are present. If not no events will be sent. This has the advantage * that we stop distributing events after the camunda-bpm-osgi-eventing bundle * has been stopped but we can continue after it has been reactivated. * * @author Ronny Bräunlich */ public class EventDistributorHandler implements InvocationHandler { /** * We are just fine with the system bundle because all we do is service * lookups */ private final Bundle systemBundle; public EventDistributorHandler(BundleContext context) { this.systemBundle = context.getBundle(0); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (isObjectMethod(method)) { return handleObjectMethod(proxy, method, args); } if (isEventBridgeActivatorPresent(systemBundle.getBundleContext())) { EventAdmin eventAdmin = findEventAdmin(systemBundle.getBundleContext()); if (eventAdmin != null) { OSGiEventDistributor distributor = new OSGiEventDistributor(eventAdmin); return method.invoke(distributor, args); } } return null; } private boolean isObjectMethod(Method method) { return Object.class.equals(method.getDeclaringClass()); } private Object handleObjectMethod(Object proxy, Method method, Object[] args) { String name = method.getName(); if ("equals".equals(name)) { return proxy == args[0]; } else if ("hashCode".equals(name)) { return System.identityHashCode(proxy); } else if ("toString".equals(name)) { return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy)) + ", with InvocationHandler " + this; } else { throw new IllegalStateException(String.valueOf(method)); } } private boolean isEventBridgeActivatorPresent(BundleContext ctx) { ServiceReference<OSGiEventBridgeActivator> reference = ctx.getServiceReference(OSGiEventBridgeActivator.class); if (reference != null) { return ctx.getService(reference) != null; } return false; } private EventAdmin findEventAdmin(BundleContext ctx) { ServiceReference<EventAdmin> ref = ctx.getServiceReference(EventAdmin.class); EventAdmin eventAdmin = null; if (ref != null) { eventAdmin = ctx.getService(ref); } return eventAdmin; } }