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 <validator> 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.