Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ValidatorAction |
|
| 2.8378378378378377;2.838 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | package org.apache.commons.validator; | |
18 | ||
19 | import java.io.BufferedReader; | |
20 | import java.io.IOException; | |
21 | import java.io.InputStream; | |
22 | import java.io.InputStreamReader; | |
23 | import java.io.Serializable; | |
24 | import java.lang.reflect.InvocationTargetException; | |
25 | import java.lang.reflect.Method; | |
26 | import java.lang.reflect.Modifier; | |
27 | import java.util.ArrayList; | |
28 | import java.util.Collections; | |
29 | import java.util.List; | |
30 | import java.util.Map; | |
31 | import java.util.StringTokenizer; | |
32 | ||
33 | import org.apache.commons.logging.Log; | |
34 | import org.apache.commons.logging.LogFactory; | |
35 | import org.apache.commons.validator.util.ValidatorUtils; | |
36 | ||
37 | /** | |
38 | * Contains the information to dynamically create and run a validation | |
39 | * method. This is the class representation of a pluggable validator that can | |
40 | * be defined in an xml file with the <validator> element. | |
41 | * | |
42 | * <strong>Note</strong>: The validation method is assumed to be thread safe. | |
43 | * | |
44 | * @version $Revision: 1739361 $ | |
45 | */ | |
46 | 384 | public class ValidatorAction implements Serializable { |
47 | ||
48 | private static final long serialVersionUID = 1339713700053204597L; | |
49 | ||
50 | /** | |
51 | * Logger. | |
52 | */ | |
53 | 384 | private transient Log log = LogFactory.getLog(ValidatorAction.class); |
54 | ||
55 | /** | |
56 | * The name of the validation. | |
57 | */ | |
58 | 384 | private String name = null; |
59 | ||
60 | /** | |
61 | * The full class name of the class containing | |
62 | * the validation method associated with this action. | |
63 | */ | |
64 | 384 | private String classname = null; |
65 | ||
66 | /** | |
67 | * The Class object loaded from the classname. | |
68 | */ | |
69 | 384 | private Class<?> validationClass = null; |
70 | ||
71 | /** | |
72 | * The full method name of the validation to be performed. The method | |
73 | * must be thread safe. | |
74 | */ | |
75 | 384 | private String method = null; |
76 | ||
77 | /** | |
78 | * The Method object loaded from the method name. | |
79 | */ | |
80 | 384 | private Method validationMethod = null; |
81 | ||
82 | /** | |
83 | * <p> | |
84 | * The method signature of the validation method. This should be a comma | |
85 | * delimited list of the full class names of each parameter in the correct | |
86 | * order that the method takes. | |
87 | * </p> | |
88 | * <p> | |
89 | * Note: <code>java.lang.Object</code> is reserved for the | |
90 | * JavaBean that is being validated. The <code>ValidatorAction</code> | |
91 | * and <code>Field</code> that are associated with a field's | |
92 | * validation will automatically be populated if they are | |
93 | * specified in the method signature. | |
94 | * </p> | |
95 | */ | |
96 | 384 | private String methodParams = |
97 | Validator.BEAN_PARAM | |
98 | + "," | |
99 | + Validator.VALIDATOR_ACTION_PARAM | |
100 | + "," | |
101 | + Validator.FIELD_PARAM; | |
102 | ||
103 | /** | |
104 | * The Class objects for each entry in methodParameterList. | |
105 | */ | |
106 | 384 | private Class<?>[] parameterClasses = null; |
107 | ||
108 | /** | |
109 | * The other <code>ValidatorAction</code>s that this one depends on. If | |
110 | * any errors occur in an action that this one depends on, this action will | |
111 | * not be processsed. | |
112 | */ | |
113 | 384 | private String depends = null; |
114 | ||
115 | /** | |
116 | * The default error message associated with this action. | |
117 | */ | |
118 | 384 | private String msg = null; |
119 | ||
120 | /** | |
121 | * An optional field to contain the name to be used if JavaScript is | |
122 | * generated. | |
123 | */ | |
124 | 384 | private String jsFunctionName = null; |
125 | ||
126 | /** | |
127 | * An optional field to contain the class path to be used to retrieve the | |
128 | * JavaScript function. | |
129 | */ | |
130 | 384 | private String jsFunction = null; |
131 | ||
132 | /** | |
133 | * An optional field to containing a JavaScript representation of the | |
134 | * java method assocated with this action. | |
135 | */ | |
136 | 384 | private String javascript = null; |
137 | ||
138 | /** | |
139 | * If the java method matching the correct signature isn't static, the | |
140 | * instance is stored in the action. This assumes the method is thread | |
141 | * safe. | |
142 | */ | |
143 | 384 | private Object instance = null; |
144 | ||
145 | /** | |
146 | * An internal List representation of the other <code>ValidatorAction</code>s | |
147 | * this one depends on (if any). This List gets updated | |
148 | * whenever setDepends() gets called. This is synchronized so a call to | |
149 | * setDepends() (which clears the List) won't interfere with a call to | |
150 | * isDependency(). | |
151 | */ | |
152 | 384 | private final List<String> dependencyList = Collections.synchronizedList(new ArrayList<String>()); |
153 | ||
154 | /** | |
155 | * An internal List representation of all the validation method's | |
156 | * parameters defined in the methodParams String. | |
157 | */ | |
158 | 384 | private final List<String> methodParameterList = new ArrayList<String>(); |
159 | ||
160 | /** | |
161 | * Gets the name of the validator action. | |
162 | * @return Validator Action name. | |
163 | */ | |
164 | public String getName() { | |
165 | 398 | return name; |
166 | } | |
167 | ||
168 | /** | |
169 | * Sets the name of the validator action. | |
170 | * @param name Validator Action name. | |
171 | */ | |
172 | public void setName(String name) { | |
173 | 384 | this.name = name; |
174 | 384 | } |
175 | ||
176 | /** | |
177 | * Gets the class of the validator action. | |
178 | * @return Class name of the validator Action. | |
179 | */ | |
180 | public String getClassname() { | |
181 | 0 | return classname; |
182 | } | |
183 | ||
184 | /** | |
185 | * Sets the class of the validator action. | |
186 | * @param classname Class name of the validator Action. | |
187 | */ | |
188 | public void setClassname(String classname) { | |
189 | 384 | this.classname = classname; |
190 | 384 | } |
191 | ||
192 | /** | |
193 | * Gets the name of method being called for the validator action. | |
194 | * @return The method name. | |
195 | */ | |
196 | public String getMethod() { | |
197 | 0 | return method; |
198 | } | |
199 | ||
200 | /** | |
201 | * Sets the name of method being called for the validator action. | |
202 | * @param method The method name. | |
203 | */ | |
204 | public void setMethod(String method) { | |
205 | 384 | this.method = method; |
206 | 384 | } |
207 | ||
208 | /** | |
209 | * Gets the method parameters for the method. | |
210 | * @return Method's parameters. | |
211 | */ | |
212 | public String getMethodParams() { | |
213 | 0 | return methodParams; |
214 | } | |
215 | ||
216 | /** | |
217 | * Sets the method parameters for the method. | |
218 | * @param methodParams A comma separated list of parameters. | |
219 | */ | |
220 | public void setMethodParams(String methodParams) { | |
221 | 384 | this.methodParams = methodParams; |
222 | ||
223 | 384 | this.methodParameterList.clear(); |
224 | ||
225 | 384 | StringTokenizer st = new StringTokenizer(methodParams, ","); |
226 | 1186 | while (st.hasMoreTokens()) { |
227 | 802 | String value = st.nextToken().trim(); |
228 | ||
229 | 802 | if (value != null && value.length() > 0) { |
230 | 802 | this.methodParameterList.add(value); |
231 | } | |
232 | 802 | } |
233 | 384 | } |
234 | ||
235 | /** | |
236 | * Gets the dependencies of the validator action as a comma separated list | |
237 | * of validator names. | |
238 | * @return The validator action's dependencies. | |
239 | */ | |
240 | public String getDepends() { | |
241 | 0 | return this.depends; |
242 | } | |
243 | ||
244 | /** | |
245 | * Sets the dependencies of the validator action. | |
246 | * @param depends A comma separated list of validator names. | |
247 | */ | |
248 | public void setDepends(String depends) { | |
249 | 10 | this.depends = depends; |
250 | ||
251 | 10 | this.dependencyList.clear(); |
252 | ||
253 | 10 | StringTokenizer st = new StringTokenizer(depends, ","); |
254 | 28 | while (st.hasMoreTokens()) { |
255 | 18 | String depend = st.nextToken().trim(); |
256 | ||
257 | 18 | if (depend != null && depend.length() > 0) { |
258 | 18 | this.dependencyList.add(depend); |
259 | } | |
260 | 18 | } |
261 | 10 | } |
262 | ||
263 | /** | |
264 | * Gets the message associated with the validator action. | |
265 | * @return The message for the validator action. | |
266 | */ | |
267 | public String getMsg() { | |
268 | 0 | return msg; |
269 | } | |
270 | ||
271 | /** | |
272 | * Sets the message associated with the validator action. | |
273 | * @param msg The message for the validator action. | |
274 | */ | |
275 | public void setMsg(String msg) { | |
276 | 380 | this.msg = msg; |
277 | 380 | } |
278 | ||
279 | /** | |
280 | * Gets the Javascript function name. This is optional and can | |
281 | * be used instead of validator action name for the name of the | |
282 | * Javascript function/object. | |
283 | * @return The Javascript function name. | |
284 | */ | |
285 | public String getJsFunctionName() { | |
286 | 0 | return jsFunctionName; |
287 | } | |
288 | ||
289 | /** | |
290 | * Sets the Javascript function name. This is optional and can | |
291 | * be used instead of validator action name for the name of the | |
292 | * Javascript function/object. | |
293 | * @param jsFunctionName The Javascript function name. | |
294 | */ | |
295 | public void setJsFunctionName(String jsFunctionName) { | |
296 | 0 | this.jsFunctionName = jsFunctionName; |
297 | 0 | } |
298 | ||
299 | /** | |
300 | * Sets the fully qualified class path of the Javascript function. | |
301 | * <p> | |
302 | * This is optional and can be used <strong>instead</strong> of the setJavascript(). | |
303 | * Attempting to call both <code>setJsFunction</code> and <code>setJavascript</code> | |
304 | * will result in an <code>IllegalStateException</code> being thrown. </p> | |
305 | * <p> | |
306 | * If <strong>neither</strong> setJsFunction or setJavascript is set then | |
307 | * validator will attempt to load the default javascript definition. | |
308 | * </p> | |
309 | * <pre> | |
310 | * <b>Examples</b> | |
311 | * If in the validator.xml : | |
312 | * #1: | |
313 | * <validator name="tire" | |
314 | * jsFunction="com.yourcompany.project.tireFuncion"> | |
315 | * Validator will attempt to load com.yourcompany.project.validateTireFunction.js from | |
316 | * its class path. | |
317 | * #2: | |
318 | * <validator name="tire"> | |
319 | * Validator will use the name attribute to try and load | |
320 | * org.apache.commons.validator.javascript.validateTire.js | |
321 | * which is the default javascript definition. | |
322 | * </pre> | |
323 | * @param jsFunction The Javascript function's fully qualified class path. | |
324 | */ | |
325 | public void setJsFunction(String jsFunction) { | |
326 | 0 | if (javascript != null) { |
327 | 0 | throw new IllegalStateException("Cannot call setJsFunction() after calling setJavascript()"); |
328 | } | |
329 | ||
330 | 0 | this.jsFunction = jsFunction; |
331 | 0 | } |
332 | ||
333 | /** | |
334 | * Gets the Javascript equivalent of the java class and method | |
335 | * associated with this action. | |
336 | * @return The Javascript validation. | |
337 | */ | |
338 | public String getJavascript() { | |
339 | 0 | return javascript; |
340 | } | |
341 | ||
342 | /** | |
343 | * Sets the Javascript equivalent of the java class and method | |
344 | * associated with this action. | |
345 | * @param javascript The Javascript validation. | |
346 | */ | |
347 | public void setJavascript(String javascript) { | |
348 | 0 | if (jsFunction != null) { |
349 | 0 | throw new IllegalStateException("Cannot call setJavascript() after calling setJsFunction()"); |
350 | } | |
351 | ||
352 | 0 | this.javascript = javascript; |
353 | 0 | } |
354 | ||
355 | /** | |
356 | * Initialize based on set. | |
357 | */ | |
358 | protected void init() { | |
359 | 384 | this.loadJavascriptFunction(); |
360 | 384 | } |
361 | ||
362 | /** | |
363 | * Load the javascript function specified by the given path. For this | |
364 | * implementation, the <code>jsFunction</code> property should contain a | |
365 | * fully qualified package and script name, separated by periods, to be | |
366 | * loaded from the class loader that created this instance. | |
367 | * | |
368 | * TODO if the path begins with a '/' the path will be intepreted as | |
369 | * absolute, and remain unchanged. If this fails then it will attempt to | |
370 | * treat the path as a file path. It is assumed the script ends with a | |
371 | * '.js'. | |
372 | */ | |
373 | protected synchronized void loadJavascriptFunction() { | |
374 | ||
375 | 384 | if (this.javascriptAlreadyLoaded()) { |
376 | 0 | return; |
377 | } | |
378 | ||
379 | 384 | if (getLog().isTraceEnabled()) { |
380 | 0 | getLog().trace(" Loading function begun"); |
381 | } | |
382 | ||
383 | 384 | if (this.jsFunction == null) { |
384 | 384 | this.jsFunction = this.generateJsFunction(); |
385 | } | |
386 | ||
387 | 384 | String javascriptFileName = this.formatJavascriptFileName(); |
388 | ||
389 | 384 | if (getLog().isTraceEnabled()) { |
390 | 0 | getLog().trace(" Loading js function '" + javascriptFileName + "'"); |
391 | } | |
392 | ||
393 | 384 | this.javascript = this.readJavascriptFile(javascriptFileName); |
394 | ||
395 | 384 | if (getLog().isTraceEnabled()) { |
396 | 0 | getLog().trace(" Loading javascript function completed"); |
397 | } | |
398 | ||
399 | 384 | } |
400 | ||
401 | /** | |
402 | * Read a javascript function from a file. | |
403 | * @param javascriptFileName The file containing the javascript. | |
404 | * @return The javascript function or null if it could not be loaded. | |
405 | */ | |
406 | private String readJavascriptFile(String javascriptFileName) { | |
407 | 384 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); |
408 | 384 | if (classLoader == null) { |
409 | 0 | classLoader = this.getClass().getClassLoader(); |
410 | } | |
411 | ||
412 | 384 | InputStream is = classLoader.getResourceAsStream(javascriptFileName); |
413 | 384 | if (is == null) { |
414 | 384 | is = this.getClass().getResourceAsStream(javascriptFileName); |
415 | } | |
416 | ||
417 | 384 | if (is == null) { |
418 | 384 | getLog().debug(" Unable to read javascript name "+javascriptFileName); |
419 | 384 | return null; |
420 | } | |
421 | ||
422 | 0 | StringBuilder buffer = new StringBuilder(); |
423 | 0 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // TODO encoding |
424 | try { | |
425 | 0 | String line = null; |
426 | 0 | while ((line = reader.readLine()) != null) { |
427 | 0 | buffer.append(line).append("\n"); |
428 | } | |
429 | ||
430 | 0 | } catch(IOException e) { |
431 | 0 | getLog().error("Error reading javascript file.", e); |
432 | ||
433 | } finally { | |
434 | 0 | try { |
435 | 0 | reader.close(); |
436 | 0 | } catch(IOException e) { |
437 | 0 | getLog().error("Error closing stream to javascript file.", e); |
438 | 0 | } |
439 | 0 | } |
440 | ||
441 | 0 | String function = buffer.toString(); |
442 | 0 | return function.equals("") ? null : function; |
443 | } | |
444 | ||
445 | /** | |
446 | * @return A filename suitable for passing to a | |
447 | * ClassLoader.getResourceAsStream() method. | |
448 | */ | |
449 | private String formatJavascriptFileName() { | |
450 | 384 | String name = this.jsFunction.substring(1); |
451 | ||
452 | 384 | if (!this.jsFunction.startsWith("/")) { |
453 | 384 | name = jsFunction.replace('.', '/') + ".js"; |
454 | } | |
455 | ||
456 | 384 | return name; |
457 | } | |
458 | ||
459 | /** | |
460 | * @return true if the javascript for this action has already been loaded. | |
461 | */ | |
462 | private boolean javascriptAlreadyLoaded() { | |
463 | 384 | return (this.javascript != null); |
464 | } | |
465 | ||
466 | /** | |
467 | * Used to generate the javascript name when it is not specified. | |
468 | */ | |
469 | private String generateJsFunction() { | |
470 | 384 | StringBuilder jsName = |
471 | new StringBuilder("org.apache.commons.validator.javascript"); | |
472 | ||
473 | 384 | jsName.append(".validate"); |
474 | 384 | jsName.append(name.substring(0, 1).toUpperCase()); |
475 | 384 | jsName.append(name.substring(1, name.length())); |
476 | ||
477 | 384 | return jsName.toString(); |
478 | } | |
479 | ||
480 | /** | |
481 | * Checks whether or not the value passed in is in the depends field. | |
482 | * @param validatorName Name of the dependency to check. | |
483 | * @return Whether the named validator is a dependant. | |
484 | */ | |
485 | public boolean isDependency(String validatorName) { | |
486 | 0 | return this.dependencyList.contains(validatorName); |
487 | } | |
488 | ||
489 | /** | |
490 | * Returns the dependent validator names as an unmodifiable | |
491 | * <code>List</code>. | |
492 | * @return List of the validator action's depedents. | |
493 | */ | |
494 | public List<String> getDependencyList() { | |
495 | 208 | return Collections.unmodifiableList(this.dependencyList); |
496 | } | |
497 | ||
498 | /** | |
499 | * Returns a string representation of the object. | |
500 | * @return a string representation. | |
501 | */ | |
502 | @Override | |
503 | public String toString() { | |
504 | 0 | StringBuilder results = new StringBuilder("ValidatorAction: "); |
505 | 0 | results.append(name); |
506 | 0 | results.append("\n"); |
507 | ||
508 | 0 | return results.toString(); |
509 | } | |
510 | ||
511 | /** | |
512 | * Dynamically runs the validation method for this validator and returns | |
513 | * true if the data is valid. | |
514 | * @param field | |
515 | * @param params A Map of class names to parameter values. | |
516 | * @param results | |
517 | * @param pos The index of the list property to validate if it's indexed. | |
518 | * @throws ValidatorException | |
519 | */ | |
520 | boolean executeValidationMethod( | |
521 | Field field, | |
522 | // TODO What is this the correct value type? | |
523 | // both ValidatorAction and Validator are added as parameters | |
524 | Map<String, Object> params, | |
525 | ValidatorResults results, | |
526 | int pos) | |
527 | throws ValidatorException { | |
528 | ||
529 | 201 | params.put(Validator.VALIDATOR_ACTION_PARAM, this); |
530 | ||
531 | try { | |
532 | 201 | if (this.validationMethod == null) { |
533 | 131 | synchronized(this) { |
534 | 131 | ClassLoader loader = this.getClassLoader(params); |
535 | 131 | this.loadValidationClass(loader); |
536 | 131 | this.loadParameterClasses(loader); |
537 | 131 | this.loadValidationMethod(); |
538 | 131 | } |
539 | } | |
540 | ||
541 | 201 | Object[] paramValues = this.getParameterValues(params); |
542 | ||
543 | 201 | if (field.isIndexed()) { |
544 | 0 | this.handleIndexedField(field, pos, paramValues); |
545 | } | |
546 | ||
547 | 201 | Object result = null; |
548 | try { | |
549 | 201 | result = |
550 | validationMethod.invoke( | |
551 | getValidationClassInstance(), | |
552 | paramValues); | |
553 | ||
554 | 0 | } catch (IllegalArgumentException e) { |
555 | 0 | throw new ValidatorException(e.getMessage()); |
556 | 0 | } catch (IllegalAccessException e) { |
557 | 0 | throw new ValidatorException(e.getMessage()); |
558 | 1 | } catch (InvocationTargetException e) { |
559 | ||
560 | 1 | if (e.getTargetException() instanceof Exception) { |
561 | 1 | throw (Exception) e.getTargetException(); |
562 | ||
563 | 0 | } else if (e.getTargetException() instanceof Error) { |
564 | 0 | throw (Error) e.getTargetException(); |
565 | } | |
566 | 200 | } |
567 | ||
568 | 200 | boolean valid = this.isValid(result); |
569 | 200 | if (!valid || (valid && !onlyReturnErrors(params))) { |
570 | 199 | results.add(field, this.name, valid, result); |
571 | } | |
572 | ||
573 | 200 | if (!valid) { |
574 | 95 | return false; |
575 | } | |
576 | ||
577 | // TODO This catch block remains for backward compatibility. Remove | |
578 | // this for Validator 2.0 when exception scheme changes. | |
579 | 1 | } catch (Exception e) { |
580 | 1 | if (e instanceof ValidatorException) { |
581 | 1 | throw (ValidatorException) e; |
582 | } | |
583 | ||
584 | 0 | getLog().error( |
585 | "Unhandled exception thrown during validation: " + e.getMessage(), | |
586 | e); | |
587 | ||
588 | 0 | results.add(field, this.name, false); |
589 | 0 | return false; |
590 | 105 | } |
591 | ||
592 | 105 | return true; |
593 | } | |
594 | ||
595 | /** | |
596 | * Load the Method object for the configured validation method name. | |
597 | * @throws ValidatorException | |
598 | */ | |
599 | private void loadValidationMethod() throws ValidatorException { | |
600 | 131 | if (this.validationMethod != null) { |
601 | 0 | return; |
602 | } | |
603 | ||
604 | try { | |
605 | 131 | this.validationMethod = |
606 | this.validationClass.getMethod(this.method, this.parameterClasses); | |
607 | ||
608 | 0 | } catch (NoSuchMethodException e) { |
609 | 0 | throw new ValidatorException("No such validation method: " + |
610 | e.getMessage()); | |
611 | 131 | } |
612 | 131 | } |
613 | ||
614 | /** | |
615 | * Load the Class object for the configured validation class name. | |
616 | * @param loader The ClassLoader used to load the Class object. | |
617 | * @throws ValidatorException | |
618 | */ | |
619 | private void loadValidationClass(ClassLoader loader) | |
620 | throws ValidatorException { | |
621 | ||
622 | 131 | if (this.validationClass != null) { |
623 | 0 | return; |
624 | } | |
625 | ||
626 | try { | |
627 | 131 | this.validationClass = loader.loadClass(this.classname); |
628 | 0 | } catch (ClassNotFoundException e) { |
629 | 0 | throw new ValidatorException(e.toString()); |
630 | 131 | } |
631 | 131 | } |
632 | ||
633 | /** | |
634 | * Converts a List of parameter class names into their Class objects. | |
635 | * Stores the output in {@link parameterClasses}. This | |
636 | * array is in the same order as the given List and is suitable for passing | |
637 | * to the validation method. | |
638 | * @throws ValidatorException if a class cannot be loaded. | |
639 | */ | |
640 | private void loadParameterClasses(ClassLoader loader) | |
641 | throws ValidatorException { | |
642 | ||
643 | 131 | if (this.parameterClasses != null) { |
644 | 0 | return; |
645 | } | |
646 | ||
647 | 131 | Class<?>[] parameterClasses = new Class[this.methodParameterList.size()]; |
648 | ||
649 | 418 | for (int i = 0; i < this.methodParameterList.size(); i++) { |
650 | 287 | String paramClassName = this.methodParameterList.get(i); |
651 | ||
652 | try { | |
653 | 287 | parameterClasses[i] = loader.loadClass(paramClassName); |
654 | ||
655 | 0 | } catch (ClassNotFoundException e) { |
656 | 0 | throw new ValidatorException(e.getMessage()); |
657 | 287 | } |
658 | } | |
659 | ||
660 | 131 | this.parameterClasses = parameterClasses; |
661 | 131 | } |
662 | ||
663 | /** | |
664 | * Converts a List of parameter class names into their values contained in | |
665 | * the parameters Map. | |
666 | * @param params A Map of class names to parameter values. | |
667 | * @return An array containing the value object for each parameter. This | |
668 | * array is in the same order as the given List and is suitable for passing | |
669 | * to the validation method. | |
670 | */ | |
671 | private Object[] getParameterValues(Map<String, ? super Object> params) { | |
672 | ||
673 | 201 | Object[] paramValue = new Object[this.methodParameterList.size()]; |
674 | ||
675 | 634 | for (int i = 0; i < this.methodParameterList.size(); i++) { |
676 | 433 | String paramClassName = this.methodParameterList.get(i); |
677 | 433 | paramValue[i] = params.get(paramClassName); |
678 | } | |
679 | ||
680 | 201 | return paramValue; |
681 | } | |
682 | ||
683 | /** | |
684 | * Return an instance of the validation class or null if the validation | |
685 | * method is static so does not require an instance to be executed. | |
686 | */ | |
687 | private Object getValidationClassInstance() throws ValidatorException { | |
688 | 201 | if (Modifier.isStatic(this.validationMethod.getModifiers())) { |
689 | 201 | this.instance = null; |
690 | ||
691 | } else { | |
692 | 0 | if (this.instance == null) { |
693 | try { | |
694 | 0 | this.instance = this.validationClass.newInstance(); |
695 | 0 | } catch (InstantiationException e) { |
696 | 0 | String msg = |
697 | "Couldn't create instance of " | |
698 | + this.classname | |
699 | + ". " | |
700 | + e.getMessage(); | |
701 | ||
702 | 0 | throw new ValidatorException(msg); |
703 | ||
704 | 0 | } catch (IllegalAccessException e) { |
705 | 0 | String msg = |
706 | "Couldn't create instance of " | |
707 | + this.classname | |
708 | + ". " | |
709 | + e.getMessage(); | |
710 | ||
711 | 0 | throw new ValidatorException(msg); |
712 | 0 | } |
713 | } | |
714 | } | |
715 | ||
716 | 201 | return this.instance; |
717 | } | |
718 | ||
719 | /** | |
720 | * Modifies the paramValue array with indexed fields. | |
721 | * | |
722 | * @param field | |
723 | * @param pos | |
724 | * @param paramValues | |
725 | */ | |
726 | private void handleIndexedField(Field field, int pos, Object[] paramValues) | |
727 | throws ValidatorException { | |
728 | ||
729 | 0 | int beanIndex = this.methodParameterList.indexOf(Validator.BEAN_PARAM); |
730 | 0 | int fieldIndex = this.methodParameterList.indexOf(Validator.FIELD_PARAM); |
731 | ||
732 | 0 | Object indexedList[] = field.getIndexedProperty(paramValues[beanIndex]); |
733 | ||
734 | // Set current iteration object to the parameter array | |
735 | 0 | paramValues[beanIndex] = indexedList[pos]; |
736 | ||
737 | // Set field clone with the key modified to represent | |
738 | // the current field | |
739 | 0 | Field indexedField = (Field) field.clone(); |
740 | 0 | indexedField.setKey( |
741 | ValidatorUtils.replace( | |
742 | indexedField.getKey(), | |
743 | Field.TOKEN_INDEXED, | |
744 | "[" + pos + "]")); | |
745 | ||
746 | 0 | paramValues[fieldIndex] = indexedField; |
747 | 0 | } |
748 | ||
749 | /** | |
750 | * If the result object is a <code>Boolean</code>, it will return its | |
751 | * value. If not it will return <code>false</code> if the object is | |
752 | * <code>null</code> and <code>true</code> if it isn't. | |
753 | */ | |
754 | private boolean isValid(Object result) { | |
755 | 200 | if (result instanceof Boolean) { |
756 | 173 | Boolean valid = (Boolean) result; |
757 | 173 | return valid.booleanValue(); |
758 | } | |
759 | 27 | return result != null; |
760 | } | |
761 | ||
762 | /** | |
763 | * Returns the ClassLoader set in the Validator contained in the parameter | |
764 | * Map. | |
765 | */ | |
766 | private ClassLoader getClassLoader(Map<String, Object> params) { | |
767 | 131 | Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM); |
768 | 131 | return v.getClassLoader(); |
769 | } | |
770 | ||
771 | /** | |
772 | * Returns the onlyReturnErrors setting in the Validator contained in the | |
773 | * parameter Map. | |
774 | */ | |
775 | private boolean onlyReturnErrors(Map<String, Object> params) { | |
776 | 105 | Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM); |
777 | 105 | return v.getOnlyReturnErrors(); |
778 | } | |
779 | ||
780 | /** | |
781 | * Accessor method for Log instance. | |
782 | * | |
783 | * The Log instance variable is transient and | |
784 | * accessing it through this method ensures it | |
785 | * is re-initialized when this instance is | |
786 | * de-serialized. | |
787 | * | |
788 | * @return The Log instance. | |
789 | */ | |
790 | private Log getLog() { | |
791 | 1536 | if (log == null) { |
792 | 0 | log = LogFactory.getLog(ValidatorAction.class); |
793 | } | |
794 | 1536 | return log; |
795 | } | |
796 | } |