Coverage report

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

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

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