%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.turbine.modules.ActionEvent |
|
|
1 | package org.apache.turbine.modules; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | import java.lang.reflect.InvocationTargetException; |
|
20 | import java.lang.reflect.Method; |
|
21 | import java.util.Iterator; |
|
22 | ||
23 | import org.apache.commons.lang.StringUtils; |
|
24 | ||
25 | import org.apache.commons.logging.Log; |
|
26 | import org.apache.commons.logging.LogFactory; |
|
27 | ||
28 | import org.apache.turbine.Turbine; |
|
29 | import org.apache.turbine.TurbineConstants; |
|
30 | import org.apache.turbine.util.RunData; |
|
31 | import org.apache.turbine.util.parser.ParameterParser; |
|
32 | import org.apache.turbine.util.parser.ParserUtils; |
|
33 | ||
34 | /** |
|
35 | * <p> |
|
36 | * |
|
37 | * This is an alternative to the Action class that allows you to do |
|
38 | * event based actions. Essentially, you label all your submit buttons |
|
39 | * with the prefix of "eventSubmit_" and the suffix of "methodName". |
|
40 | * For example, "eventSubmit_doDelete". Then any class that subclasses |
|
41 | * this class will get its "doDelete(RunData data)" method executed. |
|
42 | * If for any reason, it was not able to execute the method, it will |
|
43 | * fall back to executing the doPeform() method which is required to |
|
44 | * be implemented. |
|
45 | * |
|
46 | * <p> |
|
47 | * |
|
48 | * Limitations: |
|
49 | * |
|
50 | * <p> |
|
51 | * |
|
52 | * Because ParameterParser makes all the key values lowercase, we have |
|
53 | * to do some work to format the string into a method name. For |
|
54 | * example, a button name eventSubmit_doDelete gets converted into |
|
55 | * eventsubmit_dodelete. Thus, we need to form some sort of naming |
|
56 | * convention so that dodelete can be turned into doDelete. |
|
57 | * |
|
58 | * <p> |
|
59 | * |
|
60 | * Thus, the convention is this: |
|
61 | * |
|
62 | * <ul> |
|
63 | * <li>The variable name MUST have the prefix "eventSubmit_".</li> |
|
64 | * <li>The variable name after the prefix MUST begin with the letters |
|
65 | * "do".</li> |
|
66 | * <li>The first letter after the "do" will be capitalized and the |
|
67 | * rest will be lowercase</li> |
|
68 | * </ul> |
|
69 | * |
|
70 | * If you follow these conventions, then you should be ok with your |
|
71 | * method naming in your Action class. |
|
72 | * |
|
73 | * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens </a> |
|
74 | * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
|
75 | * @author <a href="quintonm@bellsouth.net">Quinton McCombs</a> |
|
76 | * @version $Id: ActionEvent.java 292717 2005-09-30 12:56:23Z seade $ |
|
77 | */ |
|
78 | public abstract class ActionEvent extends Action |
|
79 | { |
|
80 | /** Logging */ |
|
81 | 0 | protected Log log = LogFactory.getLog(this.getClass()); |
82 | ||
83 | /** Constant needed for Reflection */ |
|
84 | 0 | private static final Class [] methodParams |
85 | 0 | = new Class [] { RunData.class }; |
86 | ||
87 | /** |
|
88 | * You need to implement this in your classes that extend this class. |
|
89 | * |
|
90 | * @param data Turbine information. |
|
91 | * @exception Exception a generic exception. |
|
92 | */ |
|
93 | public abstract void doPerform(RunData data) |
|
94 | throws Exception; |
|
95 | ||
96 | /** The name of the button to look for. */ |
|
97 | protected static final String BUTTON = "eventSubmit_"; |
|
98 | /** The length of the button to look for. */ |
|
99 | 0 | protected static final int BUTTON_LENGTH = BUTTON.length(); |
100 | /** The prefix of the method name. */ |
|
101 | protected static final String METHOD_NAME_PREFIX = "do"; |
|
102 | /** The length of the method name. */ |
|
103 | 0 | protected static final int METHOD_NAME_LENGTH = METHOD_NAME_PREFIX.length(); |
104 | /** The length of the button to look for. */ |
|
105 | 0 | protected static final int LENGTH = BUTTON.length(); |
106 | ||
107 | /** |
|
108 | * If true, the eventSubmit_do<xxx> variable must contain |
|
109 | * a not null value to be executed. |
|
110 | */ |
|
111 | 0 | private boolean submitValueKey = false; |
112 | ||
113 | /** |
|
114 | * C'tor |
|
115 | */ |
|
116 | public ActionEvent() |
|
117 | { |
|
118 | 0 | super(); |
119 | ||
120 | 0 | submitValueKey = Turbine.getConfiguration() |
121 | .getBoolean(TurbineConstants.ACTION_EVENTSUBMIT_NEEDSVALUE_KEY, |
|
122 | TurbineConstants.ACTION_EVENTSUBMIT_NEEDSVALUE_DEFAULT); |
|
123 | ||
124 | 0 | log.debug(submitValueKey |
125 | ? "ActionEvent accepts only eventSubmit_do Keys with a value != 0" |
|
126 | : "ActionEvent accepts all eventSubmit_do Keys"); |
|
127 | 0 | } |
128 | ||
129 | /** |
|
130 | * This overrides the default Action.perform() to execute the |
|
131 | * doEvent() method. If that fails, then it will execute the |
|
132 | * doPerform() method instead. |
|
133 | * |
|
134 | * @param data Turbine information. |
|
135 | * @exception Exception a generic exception. |
|
136 | */ |
|
137 | protected void perform(RunData data) |
|
138 | throws Exception |
|
139 | { |
|
140 | try |
|
141 | { |
|
142 | 0 | executeEvents(data); |
143 | } |
|
144 | 0 | catch (NoSuchMethodException e) |
145 | { |
|
146 | 0 | doPerform(data); |
147 | 0 | } |
148 | 0 | } |
149 | ||
150 | /** |
|
151 | * This method should be called to execute the event based system. |
|
152 | * |
|
153 | * @param data Turbine information. |
|
154 | * @exception Exception a generic exception. |
|
155 | */ |
|
156 | public void executeEvents(RunData data) |
|
157 | throws Exception |
|
158 | { |
|
159 | // Name of the button. |
|
160 | 0 | String theButton = null; |
161 | // Parameter parser. |
|
162 | 0 | ParameterParser pp = data.getParameters(); |
163 | ||
164 | 0 | String button = pp.convert(BUTTON); |
165 | 0 | String key = null; |
166 | ||
167 | // Loop through and find the button. |
|
168 | 0 | for (Iterator it = pp.keySet().iterator(); it.hasNext();) |
169 | { |
|
170 | 0 | key = (String) it.next(); |
171 | 0 | if (key.startsWith(button)) |
172 | { |
|
173 | 0 | if (considerKey(key, pp)) |
174 | { |
|
175 | 0 | theButton = formatString(key); |
176 | 0 | break; |
177 | } |
|
178 | } |
|
179 | } |
|
180 | ||
181 | 0 | if (theButton == null) |
182 | { |
|
183 | 0 | throw new NoSuchMethodException("ActionEvent: The button was null"); |
184 | } |
|
185 | ||
186 | try |
|
187 | { |
|
188 | 0 | Method method = getClass().getMethod(theButton, methodParams); |
189 | 0 | Object[] methodArgs = new Object[] { data }; |
190 | ||
191 | 0 | if (log.isDebugEnabled()) |
192 | { |
|
193 | 0 | log.debug("Invoking " + method); |
194 | } |
|
195 | ||
196 | 0 | method.invoke(this, methodArgs); |
197 | } |
|
198 | 0 | catch (InvocationTargetException ite) |
199 | { |
|
200 | 0 | Throwable t = ite.getTargetException(); |
201 | 0 | if (t instanceof Exception) |
202 | { |
|
203 | 0 | throw (Exception) t; |
204 | } |
|
205 | else |
|
206 | { |
|
207 | 0 | throw ite; |
208 | } |
|
209 | } |
|
210 | finally |
|
211 | { |
|
212 | 0 | pp.remove(key); |
213 | 0 | } |
214 | 0 | } |
215 | ||
216 | /** |
|
217 | * This method does the conversion of the lowercase method name |
|
218 | * into the proper case. |
|
219 | * |
|
220 | * @param input The unconverted method name. |
|
221 | * @return A string with the method name in the proper case. |
|
222 | */ |
|
223 | protected final String formatString(String input) |
|
224 | { |
|
225 | 0 | String tmp = input; |
226 | ||
227 | 0 | if (StringUtils.isNotEmpty(input)) |
228 | { |
|
229 | 0 | tmp = input.toLowerCase(); |
230 | ||
231 | // Chop off suffixes (for image type) |
|
232 | 0 | input = (tmp.endsWith(".x") || tmp.endsWith(".y")) |
233 | ? input.substring(0, input.length() - 2) |
|
234 | : input; |
|
235 | ||
236 | 0 | if (ParserUtils.getUrlFolding() |
237 | != ParserUtils.URL_CASE_FOLDING_NONE) |
|
238 | { |
|
239 | 0 | tmp = input.toLowerCase().substring(BUTTON_LENGTH + METHOD_NAME_LENGTH); |
240 | 0 | tmp = METHOD_NAME_PREFIX + StringUtils.capitalize(tmp); |
241 | } |
|
242 | else |
|
243 | { |
|
244 | 0 | tmp = input.substring(BUTTON_LENGTH); |
245 | } |
|
246 | } |
|
247 | 0 | return tmp; |
248 | } |
|
249 | ||
250 | /** |
|
251 | * Checks whether the selected key really is a valid event. |
|
252 | * |
|
253 | * @param key The selected key |
|
254 | * @param pp The parameter parser to look for the key value |
|
255 | * |
|
256 | * @return true if this key is really an ActionEvent Key |
|
257 | */ |
|
258 | protected boolean considerKey(String key, ParameterParser pp) |
|
259 | { |
|
260 | 0 | if (!submitValueKey) |
261 | { |
|
262 | 0 | log.debug("No Value required, accepting " + key); |
263 | 0 | return true; |
264 | } |
|
265 | else |
|
266 | { |
|
267 | // If the action.eventsubmit.needsvalue key is true, |
|
268 | // events with a "0" or empty value are ignored. |
|
269 | // This can be used if you have multiple eventSubmit_do<xxx> |
|
270 | // fields in your form which are selected by client side code, |
|
271 | // e.g. JavaScript. |
|
272 | // |
|
273 | // If this key is unset or missing, nothing changes for the |
|
274 | // current behaviour. |
|
275 | // |
|
276 | 0 | String keyValue = pp.getString(key); |
277 | 0 | log.debug("Key Value is " + keyValue); |
278 | 0 | if (StringUtils.isEmpty(keyValue)) |
279 | { |
|
280 | 0 | log.debug("Key is empty, rejecting " + key); |
281 | 0 | return false; |
282 | } |
|
283 | ||
284 | try |
|
285 | { |
|
286 | 0 | if (Integer.parseInt(keyValue) != 0) |
287 | { |
|
288 | 0 | log.debug("Integer != 0, accepting " + key); |
289 | 0 | return true; |
290 | } |
|
291 | } |
|
292 | 0 | catch (NumberFormatException nfe) |
293 | { |
|
294 | // Not a number. So it might be a |
|
295 | // normal Key like "continue" or "exit". Accept |
|
296 | // it. |
|
297 | 0 | log.debug("Not a number, accepting " + key); |
298 | 0 | return true; |
299 | 0 | } |
300 | } |
|
301 | 0 | log.debug("Rejecting " + key); |
302 | 0 | return false; |
303 | } |
|
304 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |