1 /* 2 * Copyright (c) 2002-2006 by OpenSymphony 3 * All rights reserved. 4 */ 5 package com.opensymphony.xwork2.interceptor; 6 7 import com.opensymphony.xwork2.ActionInvocation; 8 import com.opensymphony.xwork2.util.logging.Logger; 9 import com.opensymphony.xwork2.util.logging.LoggerFactory; 10 11 import java.lang.reflect.InvocationTargetException; 12 import java.lang.reflect.Method; 13 14 /** 15 * A utility class for invoking prefixed methods in action class. 16 * 17 * Interceptors that made use of this class are: 18 * <ul> 19 * <li>DefaultWorkflowInterceptor</li> 20 * <li>PrepareInterceptor</li> 21 * </ul> 22 * 23 * <p/> 24 * 25 * <!-- START SNIPPET: javadocDefaultWorkflowInterceptor --> 26 * 27 * <b>In DefaultWorkflowInterceptor</b> 28 * <p>applies only when action implements {@link com.opensymphony.xwork2.Validateable}</p> 29 * <ol> 30 * <li>if the action class have validate{MethodName}(), it will be invoked</li> 31 * <li>else if the action class have validateDo{MethodName}(), it will be invoked</li> 32 * <li>no matter if 1] or 2] is performed, if alwaysInvokeValidate property of the interceptor is "true" (which is by default "true"), validate() will be invoked.</li> 33 * </ol> 34 * 35 * <!-- END SNIPPET: javadocDefaultWorkflowInterceptor --> 36 * 37 * 38 * <!-- START SNIPPET: javadocPrepareInterceptor --> 39 * 40 * <b>In PrepareInterceptor</b> 41 * <p>Applies only when action implements Preparable</p> 42 * <ol> 43 * <li>if the action class have prepare{MethodName}(), it will be invoked</li> 44 * <li>else if the action class have prepareDo(MethodName()}(), it will be invoked</li> 45 * <li>no matter if 1] or 2] is performed, if alwaysinvokePrepare property of the interceptor is "true" (which is by default "true"), prepare() will be invoked.</li> 46 * </ol> 47 * 48 * <!-- END SNIPPET: javadocPrepareInterceptor --> 49 * 50 * @author Philip Luppens 51 * @author tm_jee 52 */ 53 public class PrefixMethodInvocationUtil { 54 55 private static final Logger LOG = LoggerFactory.getLogger(PrefixMethodInvocationUtil.class); 56 57 private static final String DEFAULT_INVOCATION_METHODNAME = "execute"; 58 59 /** 60 * This method will prefix <code>actionInvocation</code>'s <code>ActionProxy</code>'s 61 * <code>method</code> with <code>prefixes</code> before invoking the prefixed method. 62 * Order of the <code>prefixes</code> is important, as this method will return once 63 * a prefixed method is found in the action class. 64 * 65 * <p/> 66 * 67 * For example, with 68 * <pre> 69 * invokePrefixMethod(actionInvocation, new String[] { "prepare", "prepareDo" }); 70 * </pre> 71 * 72 * Assuming <code>actionInvocation.getProxy(),getMethod()</code> returns "submit", 73 * the order of invocation would be as follows:- 74 * <ol> 75 * <li>prepareSubmit()</li> 76 * <li>prepareDoSubmit()</li> 77 * </ol> 78 * 79 * If <code>prepareSubmit()</code> exists, it will be invoked and this method 80 * will return, <code>prepareDoSubmit()</code> will NOT be invoked. 81 * 82 * <p/> 83 * 84 * On the other hand, if <code>prepareDoSubmit()</code> does not exists, and 85 * <code>prepareDoSubmit()</code> exists, it will be invoked. 86 * 87 * <p/> 88 * 89 * If none of those two methods exists, nothing will be invoked. 90 * 91 * @param actionInvocation the action invocation 92 * @param prefixes prefixes for method names 93 * @throws InvocationTargetException is thrown if invocation of a method failed. 94 * @throws IllegalAccessException is thrown if invocation of a method failed. 95 */ 96 public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException { 97 Object action = actionInvocation.getAction(); 98 99 String methodName = actionInvocation.getProxy().getMethod(); 100 101 if (methodName == null) { 102 // if null returns (possible according to the docs), use the default execute 103 methodName = DEFAULT_INVOCATION_METHODNAME; 104 } 105 106 Method method = getPrefixedMethod(prefixes, methodName, action); 107 if (method != null) { 108 method.invoke(action, new Object[0]); 109 } 110 } 111 112 113 /** 114 * This method returns a {@link Method} in <code>action</code>. The method 115 * returned is found by searching for method in <code>action</code> whose method name 116 * is equals to the result of appending each <code>prefixes</code> 117 * to <code>methodName</code>. Only the first method found will be returned, hence 118 * the order of <code>prefixes</code> is important. If none is found this method 119 * will return null. 120 * 121 * @param prefixes the prefixes to prefix the <code>methodName</code> 122 * @param methodName the method name to be prefixed with <code>prefixes</code> 123 * @param action the action class of which the prefixed method is to be search for. 124 * @return a {@link Method} if one is found, else <tt>null</tt>. 125 */ 126 public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) { 127 assert(prefixes != null); 128 String capitalizedMethodName = capitalizeMethodName(methodName); 129 for (String prefixe : prefixes) { 130 String prefixedMethodName = prefixe + capitalizedMethodName; 131 try { 132 return action.getClass().getMethod(prefixedMethodName, new Class[0]); 133 } 134 catch (NoSuchMethodException e) { 135 // hmm -- OK, try next prefix 136 if (LOG.isDebugEnabled()) { 137 LOG.debug("cannot find method [" + prefixedMethodName + "] in action [" + action + "]"); 138 } 139 } 140 } 141 return null; 142 } 143 144 /** 145 * This method capitalized the first character of <code>methodName</code>. 146 * <br/> 147 * eg. <code>capitalizeMethodName("someMethod");</code> will return <code>"SomeMethod"</code>. 148 * 149 * @param methodName the method name 150 * @return capitalized method name 151 */ 152 public static String capitalizeMethodName(String methodName) { 153 assert(methodName != null); 154 return methodName.substring(0, 1).toUpperCase() + methodName.substring(1); 155 } 156 157 }