1 /* 2 * $Id$ 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 package org.apache.struts.dispatcher.servlet; 22 23 import java.lang.reflect.Method; 24 25 import jakarta.servlet.http.HttpServletRequest; 26 import jakarta.servlet.http.HttpServletResponse; 27 28 import org.apache.struts.action.Action; 29 import org.apache.struts.action.ActionForm; 30 import org.apache.struts.action.ActionMapping; 31 import org.apache.struts.chain.contexts.ActionContext; 32 import org.apache.struts.chain.contexts.ServletActionContext; 33 import org.apache.struts.config.ActionConfig; 34 import org.apache.struts.dispatcher.AbstractMethodResolver; 35 36 /** 37 * This class helps resolve methods with servlet-based signatures. The following 38 * examples illustrate the method signatures supported: 39 * <ul> 40 * <li><code><i>return_type</i> execute()</code></li> 41 * <li><code><i>return_type</i> execute(ActionContext context)</code></li> 42 * <li><code><i>return_type</i> execute(ServletActionContext context)</code></li> 43 * <li><code><i>return_type</i> execute(ActionMapping mapping, ActionForm form, 44 HttpServletRequest request, HttpServletResponse response)</code></li> 45 * </ul> 46 * 47 * @version $Rev$ 48 * @since Struts 1.4 49 */ 50 public class ServletMethodResolver extends AbstractMethodResolver { 51 private static final long serialVersionUID = -4372320855532463910L; 52 53 /** 54 * The set of argument type classes for the classic reflected method call. 55 * These are the same for all calls, so calculate them only once. 56 * 57 * @see org.apache.struts.action.Action#execute(ActionMapping, ActionForm, 58 * jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse) 59 */ 60 private static final Class<?>[] CLASSIC_EXECUTE_SIGNATURE = { ActionMapping.class, ActionForm.class, 61 HttpServletRequest.class, HttpServletResponse.class }; 62 63 public Object[] buildArguments(ActionContext context, Method method) { 64 Object[] args = super.buildArguments(context, method); 65 if (args == null) { 66 Class<?>[] parameterTypes = method.getParameterTypes(); 67 switch (parameterTypes.length) { 68 case 4: 69 return buildClassicArguments((ServletActionContext) context); 70 default: 71 break; 72 } 73 } 74 return args; 75 } 76 77 /** 78 * Constructs the arguments to invoke the classic <code>execute</code> 79 * servlet signature from the specified context. 80 * 81 * @param context the current context 82 * @return the arguments array 83 * @throws NullPointerException if context is <code>null</code> 84 * @see #resolveClassicMethod(ActionContext, String) 85 */ 86 protected final Object[] buildClassicArguments(ServletActionContext context) { 87 ActionConfig mapping = context.getActionConfig(); 88 ActionForm form = context.getActionForm(); 89 HttpServletRequest request = context.getRequest(); 90 HttpServletResponse response = context.getResponse(); 91 return new Object[] { mapping, form, request, response }; 92 } 93 94 /** 95 * Obtains the method instance with the classic <code>execute</code> 96 * servlet signature. 97 * 98 * @param context the current context 99 * @param methodName the method name to introspect 100 * @return the found method in the action 101 * @throws NullPointerException if context is <code>null</code> 102 * @throws NoSuchMethodException if the method does not exist 103 * @see #buildClassicArguments(ServletActionContext) 104 * @see org.apache.struts.action.Action#execute(ActionMapping, ActionForm, 105 * jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse) 106 */ 107 protected final Method resolveClassicMethod(ActionContext context, String methodName) throws NoSuchMethodException { 108 Class<? extends Action> actionClass = context.getAction().getClass(); 109 return actionClass.getMethod(methodName, CLASSIC_EXECUTE_SIGNATURE); 110 } 111 112 public Method resolveMethod(ActionContext context, String methodName) throws NoSuchMethodException { 113 // First try to resolve anything the superclass supports 114 try { 115 return super.resolveMethod(context, methodName); 116 } catch (NoSuchMethodException e) { 117 // continue 118 } 119 120 // Can the method accept the servlet action context? 121 if (context instanceof ServletActionContext) { 122 try { 123 Class<? extends Action> actionClass = context.getAction().getClass(); 124 return actionClass.getMethod(methodName, ServletActionContext.class); 125 } catch (NoSuchMethodException e) { 126 // continue 127 } 128 } 129 130 // Lastly, try the classical argument listing 131 return resolveClassicMethod(context, methodName); 132 } 133 }