%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.turbine.modules.ActionEvent |
|
|
1 | package org.apache.turbine.modules; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2004 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,v 1.20.2.4 2004/05/20 03:03:52 seade Exp $ |
|
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 | 0 | Method method = null; |
187 | ||
188 | try |
|
189 | { |
|
190 | 0 | method = getClass().getMethod(theButton, methodParams); |
191 | 0 | Object[] methodArgs = new Object[] { data }; |
192 | ||
193 | 0 | if (log.isDebugEnabled()) |
194 | { |
|
195 | 0 | log.debug("Invoking " + method); |
196 | } |
|
197 | ||
198 | 0 | method.invoke(this, methodArgs); |
199 | } |
|
200 | 0 | catch (InvocationTargetException ite) |
201 | { |
|
202 | 0 | Throwable t = ite.getTargetException(); |
203 | 0 | log.error("Invokation of " + method , t); |
204 | } |
|
205 | finally |
|
206 | { |
|
207 | 0 | pp.remove(key); |
208 | 0 | } |
209 | 0 | } |
210 | ||
211 | /** |
|
212 | * This method does the conversion of the lowercase method name |
|
213 | * into the proper case. |
|
214 | * |
|
215 | * @param input The unconverted method name. |
|
216 | * @return A string with the method name in the proper case. |
|
217 | */ |
|
218 | protected final String formatString(String input) |
|
219 | { |
|
220 | 0 | String tmp = input; |
221 | ||
222 | 0 | if (StringUtils.isNotEmpty(input)) |
223 | { |
|
224 | 0 | tmp = input.toLowerCase(); |
225 | ||
226 | // Chop off suffixes (for image type) |
|
227 | 0 | input = (tmp.endsWith(".x") || tmp.endsWith(".y")) |
228 | ? input.substring(0, input.length() - 2) |
|
229 | : input; |
|
230 | ||
231 | 0 | if (ParserUtils.getUrlFolding() |
232 | != ParserUtils.URL_CASE_FOLDING_NONE) |
|
233 | { |
|
234 | 0 | tmp = input.toLowerCase().substring(BUTTON_LENGTH + METHOD_NAME_LENGTH); |
235 | 0 | tmp = METHOD_NAME_PREFIX + StringUtils.capitalise(tmp); |
236 | } |
|
237 | else |
|
238 | { |
|
239 | 0 | tmp = input.substring(BUTTON_LENGTH); |
240 | } |
|
241 | } |
|
242 | 0 | return tmp; |
243 | } |
|
244 | ||
245 | /** |
|
246 | * Checks whether the selected key really is a valid event. |
|
247 | * |
|
248 | * @param key The selected key |
|
249 | * @param pp The parameter parser to look for the key value |
|
250 | * |
|
251 | * @return true if this key is really an ActionEvent Key |
|
252 | */ |
|
253 | protected boolean considerKey(String key, ParameterParser pp) |
|
254 | { |
|
255 | 0 | if (!submitValueKey) |
256 | { |
|
257 | 0 | log.debug("No Value required, accepting " + key); |
258 | 0 | return true; |
259 | } |
|
260 | else |
|
261 | { |
|
262 | // If the action.eventsubmit.needsvalue key is true, |
|
263 | // events with a "0" or empty value are ignored. |
|
264 | // This can be used if you have multiple eventSubmit_do<xxx> |
|
265 | // fields in your form which are selected by client side code, |
|
266 | // e.g. JavaScript. |
|
267 | // |
|
268 | // If this key is unset or missing, nothing changes for the |
|
269 | // current behaviour. |
|
270 | // |
|
271 | 0 | String keyValue = pp.getString(key); |
272 | 0 | log.debug("Key Value is " + keyValue); |
273 | 0 | if (StringUtils.isEmpty(keyValue)) |
274 | { |
|
275 | 0 | log.debug("Key is empty, rejecting " + key); |
276 | 0 | return false; |
277 | } |
|
278 | ||
279 | try |
|
280 | { |
|
281 | 0 | if (Integer.parseInt(keyValue) != 0) |
282 | { |
|
283 | 0 | log.debug("Integer != 0, accepting " + key); |
284 | 0 | return true; |
285 | } |
|
286 | } |
|
287 | 0 | catch (NumberFormatException nfe) |
288 | { |
|
289 | // Not a number. So it might be a |
|
290 | // normal Key like "continue" or "exit". Accept |
|
291 | // it. |
|
292 | 0 | log.debug("Not a number, accepting " + key); |
293 | 0 | return true; |
294 | 0 | } |
295 | } |
|
296 | 0 | log.debug("Rejecting " + key); |
297 | 0 | return false; |
298 | } |
|
299 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |