Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.validator.ValidatorAction |
71% |
91% |

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

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.