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 }