001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.interceptor;
006:
007: import java.lang.reflect.InvocationTargetException;
008: import java.lang.reflect.Method;
009:
010: import org.apache.commons.logging.Log;
011: import org.apache.commons.logging.LogFactory;
012:
013: import com.opensymphony.xwork.ActionInvocation;
014:
015: /**
016: * A utility class for invoking prefixed methods in action class.
017: *
018: * Interceptors that made use of this class are
019: * <ul>
020: * <li>DefaultWorkflowInterceptor </li>
021: * <li>PrepareInterceptor </li>
022: * </ul>
023: *
024: * <p/>
025: *
026: * <!-- START SNIPPET: javadocDefaultWorkflowInterceptor -->
027: *
028: * <b>In DefaultWorkflowInterceptor</b>
029: * <p>applies only when action implements {@link com.opensymphony.xwork.Validateable}</p>
030: * <ol>
031: * <li>if the action class have validate{MethodName}(), it will be invoked</li>
032: * <li>else if the action class have validateDo{MethodName}(), it will be invoked</li>
033: * <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>
034: * </ol>
035: *
036: * <!-- END SNIPPET: javadocDefaultWorkflowInterceptor -->
037: *
038: *
039: * <!-- START SNIPPET: javadocPrepareInterceptor -->
040: *
041: * <b>In PrepareInterceptor</b>
042: * <p>Applies only when action implements Preparable</p>
043: * <ol>
044: * <li>if the action class have prepare{MethodName}(), it will be invoked</li>
045: * <li>else if the action class have prepareDo(MethodName()}(), it will be invoked</li>
046: * <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>
047: * </ol>
048: *
049: * <!-- END SNIPPET: javadocPrepareInterceptor -->
050: *
051: * @author Philip Luppens
052: * @author tm_jee
053: * @version $Date: 2006-07-03 19:11:57 +0200 (Mo, 03 Jul 2006) $ $Id: PrefixMethodInvocationUtil.java 1054 2006-07-03 17:11:57Z tmjee $
054: */
055: public class PrefixMethodInvocationUtil {
056:
057: private static final Log _log = LogFactory
058: .getLog(PrefixMethodInvocationUtil.class);
059:
060: /**
061: * This method will prefix <code>actionInvocation</code>'s <code>ActionProxy</code>'s
062: * <code>method</code> with <code>prefixes</code> before invoking the prefixed method.
063: * Order of the <code>prefixes</code> is important, as this method will return once
064: * a prefixed method is found in the action class.
065: *
066: * <p/>
067: *
068: * For example, with
069: * <pre>
070: * invokePrefixMethod(actionInvocation, new String[] { "prepare", "prepareDo" });
071: * </pre>
072: *
073: * Assuming <code>actionInvocation.getProxy(),getMethod()</code> returns "submit",
074: * the order of invocation would be as follows:-
075: * <ol>
076: * <li>prepareSubmit()</li>
077: * <li>prepareDoSubmit()</li>
078: * </ol>
079: *
080: * If <code>prepareSubmit()</code> exists, it will be invoked and this method
081: * will return, <code>prepareDoSubmit()</code> will NOT be invoked.
082: *
083: * <p/>
084: *
085: * On the other hand, if <code>prepareDoSubmit()</code> does not exists, and
086: * <code>prepareDoSubmit()</code> exists, it will be invoked.
087: *
088: * <p/>
089: *
090: * If none of those two methods exists, nothing will be invoked.
091: *
092: * @param actionInvocation
093: * @param prefixes
094: * @throws InvocationTargetException
095: * @throws IllegalAccessException
096: */
097: public static void invokePrefixMethod(
098: ActionInvocation actionInvocation, String[] prefixes)
099: throws InvocationTargetException, IllegalAccessException {
100: Object action = actionInvocation.getAction();
101:
102: String methodName = actionInvocation.getProxy().getMethod();
103:
104: if (methodName == null) {
105: // TODO: clean me up
106: /* if null returns (possible according to the docs),
107: * use the default execute - this should be a static somewhere ?
108: */
109: methodName = "execute";
110: }
111:
112: Method method = getPrefixedMethod(prefixes, methodName, action);
113: if (method != null) {
114: method.invoke(action, new Object[0]);
115: }
116: }
117:
118: /**
119: * This method returns a {@link Method} in <code>action</code>. The method
120: * returned is found by searching for method in <code>action</code> whose method name
121: * is equals to the result of appending each <code>prefixes</code>
122: * to <code>methodName</code>. Only the first method found will be returned, hence
123: * the order of <code>prefixes</code> is important. If none is found this method
124: * will return null.
125: *
126: * @param prefixes the prefixes to prefix the <code>methodName</code>
127: * @param methodName the method name to be prefixed with <code>prefixes</code>
128: * @param action the action class of which the prefixed method is to be search for.
129: * @return a {@link Method} if one is found, else null.
130: */
131: public static Method getPrefixedMethod(String[] prefixes,
132: String methodName, Object action) {
133: assert (prefixes != null);
134: String capitalizedMethodName = capitalizeMethodName(methodName);
135: for (int a = 0; a < prefixes.length; a++) {
136: String prefixedMethodName = prefixes[a]
137: + capitalizedMethodName;
138: try {
139: Method method = action.getClass().getMethod(
140: prefixedMethodName, new Class[0]);
141: return method;
142: } catch (NoSuchMethodException e) {
143: // hmm -- OK, try next prefix
144: if (_log.isDebugEnabled()) {
145: _log.debug("cannot find method ["
146: + prefixedMethodName + "] in action ["
147: + action + "]");
148: }
149: }
150: }
151: return null;
152: }
153:
154: /**
155: * This method capitalized the first character of <code>methodName</code>.
156: * <p/>
157: *
158: * eg.
159: * <pre>
160: * capitalizeMethodName("someMethod");
161: * </pre>
162: *
163: * will return "SomeMethod".
164: *
165: * @param methodName
166: * @return
167: */
168: public static String capitalizeMethodName(String methodName) {
169: assert (methodName != null);
170: return methodName = methodName.substring(0, 1).toUpperCase()
171: + methodName.substring(1);
172: }
173: }
|