package org.jbpm.pvm.internal.wire.operation; import java.io.Serializable; import java.lang.reflect.Method; import java.util.List; import org.jbpm.internal.log.Log; import org.jbpm.pvm.internal.util.Listener; import org.jbpm.pvm.internal.util.Observable; import org.jbpm.pvm.internal.util.ReflectUtil; import org.jbpm.pvm.internal.wire.WireContext; import org.jbpm.pvm.internal.wire.WireException; import org.jbpm.pvm.internal.wire.descriptor.ArgDescriptor; import org.jbpm.pvm.internal.wire.descriptor.ObjectDescriptor; /** * Wrapper for the subscribe operation. * This class will be used to call a specified method on reception of an event. * This class is used so that a non {@link Listener} class can subscribe to an {@link Observable} object. * * @see SubscribeOperation * * @author Tom Baeyens * @author Guillaume Porcher (Documentation) */ public class MethodInvokerListener implements Listener, Serializable { private static final long serialVersionUID = 1L; private static Log log = Log.getLog(MethodInvokerListener.class.getName()); String methodName; List argDescriptors = null; WireContext wireContext; Object target; transient Method method = null; /** * Creates a new Wrapper. * When an event is received, the arguments args are created from the list argDescriptors, and target.methodName(args) is called. * @param methodName name of the method to call when an event is received. * @param argDescriptors list of descriptors of arguments given to the method. * @param wireContext context to use to create the arguments * @param target object on which the method will be called. */ public MethodInvokerListener(String methodName, List argDescriptors, WireContext wireContext, Object target) { this.methodName = methodName; this.argDescriptors = argDescriptors; this.wireContext = wireContext; this.target = target; } public void event(Object source, String eventName, Object info) { log.debug("invoking "+methodName+" on "+target+" for event "+eventName); try { Object[] args = ObjectDescriptor.getArgs(wireContext, argDescriptors); Class clazz = target.getClass(); Method method = ReflectUtil.findMethod(clazz, methodName, argDescriptors, args); if(method == null) { throw new WireException("method "+ReflectUtil.getSignature(methodName, argDescriptors, args)+" unavailable for "+target); } ReflectUtil.invoke(method, target, args); } catch (WireException e) { throw e; } catch (Exception e) { throw new WireException("couldn't invoke listener method "+methodName+": "+e.getMessage(), e); } } }