package org.apache.commons.chain.generic; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; import java.lang.reflect.Method; import java.util.WeakHashMap; import java.lang.reflect.InvocationTargetException; /** * An abstract base command which uses introspection to look up a method to execute. * For use by developers who prefer to group related functionality into a single class * rather than an inheritance family. */ public abstract class DispatchCommand implements Command { protected WeakHashMap methods = new WeakHashMap(); protected String method = null; protected String methodKey = null; protected static final Class[] DEFAULT_SIGNATURE = new Class[] { Context.class }; public boolean execute(Context context) throws Exception { if (this.getMethod() == null && this.getMethodKey() == null) { throw new IllegalStateException("Neither 'method' nor 'methodKey' properties are defined "); } Method methodObject = extractMethod(context); return invokeMethod(methodObject, context); } protected Method extractMethod(Context context) throws NoSuchMethodException { String methodName = this.getMethod(); if (methodName == null) { methodName = context.get(this.getMethodKey()).toString(); } Method theMethod = null; synchronized (methods) { theMethod = (Method) methods.get(methodName); if (theMethod == null) { theMethod = getClass().getMethod(methodName, getSignature()); methods.put(methodName, theMethod); } } return theMethod; } protected boolean invokeMethod(Method methodObject, Context context) throws InvocationTargetException, IllegalAccessException { Boolean result = (Boolean) methodObject.invoke(this, getArguments(context)); return (result != null && result.booleanValue()); } protected Class[] getSignature() { return DEFAULT_SIGNATURE; } protected Object[] getArguments(Context context) { return new Object[] { context }; } public String getMethod() { return method; } public String getMethodKey() { return methodKey; } public void setMethod(String method) { this.method = method; } public void setMethodKey(String methodKey) { this.methodKey = methodKey; } }