001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.validator; 018 019import java.io.Serializable; 020import java.util.HashMap; 021import java.util.Locale; 022import java.util.Map; 023 024/** 025 * Validations are processed by the validate method. An instance of 026 * <code>ValidatorResources</code> is used to define the validators 027 * (validation methods) and the validation rules for a JavaBean. 028 */ 029// TODO mutable fields should be made private and accessed via suitable methods only 030public class Validator implements Serializable { 031 032 private static final long serialVersionUID = -7119418755208731611L; 033 034 /** 035 * Resources key the JavaBean is stored to perform validation on. 036 */ 037 public static final String BEAN_PARAM = "java.lang.Object"; 038 039 /** 040 * Resources key the <code>ValidatorAction</code> is stored under. 041 * This will be automatically passed into a validation method 042 * with the current <code>ValidatorAction</code> if it is 043 * specified in the method signature. 044 */ 045 public static final String VALIDATOR_ACTION_PARAM = 046 "org.apache.commons.validator.ValidatorAction"; 047 048 /** 049 * Resources key the <code>ValidatorResults</code> is stored under. 050 * This will be automatically passed into a validation method 051 * with the current <code>ValidatorResults</code> if it is 052 * specified in the method signature. 053 */ 054 public static final String VALIDATOR_RESULTS_PARAM = 055 "org.apache.commons.validator.ValidatorResults"; 056 057 /** 058 * Resources key the <code>Form</code> is stored under. 059 * This will be automatically passed into a validation method 060 * with the current <code>Form</code> if it is 061 * specified in the method signature. 062 */ 063 public static final String FORM_PARAM = "org.apache.commons.validator.Form"; 064 065 /** 066 * Resources key the <code>Field</code> is stored under. 067 * This will be automatically passed into a validation method 068 * with the current <code>Field</code> if it is 069 * specified in the method signature. 070 */ 071 public static final String FIELD_PARAM = "org.apache.commons.validator.Field"; 072 073 /** 074 * Resources key the <code>Validator</code> is stored under. 075 * This will be automatically passed into a validation method 076 * with the current <code>Validator</code> if it is 077 * specified in the method signature. 078 */ 079 public static final String VALIDATOR_PARAM = 080 "org.apache.commons.validator.Validator"; 081 082 /** 083 * Resources key the <code>Locale</code> is stored. 084 * This will be used to retrieve the appropriate 085 * <code>FormSet</code> and <code>Form</code> to be 086 * processed. 087 */ 088 public static final String LOCALE_PARAM = "java.util.Locale"; 089 090 /** 091 * The Validator Resources. 092 */ 093 protected ValidatorResources resources; 094 095 /** 096 * The name of the form to validate 097 */ 098 protected String formName; 099 100 /** 101 * The name of the field on the form to validate 102 * @since 1.2.0 103 */ 104 protected String fieldName; 105 106 /** 107 * Maps validation method parameter class names to the objects to be passed 108 * into the method. 109 */ 110 protected Map<String, Object> parameters = new HashMap<>(); // <String, Object> 111 112 /** 113 * The current page number to validate. 114 */ 115 protected int page; 116 117 /** 118 * The class loader to use for instantiating application objects. 119 * If not specified, the context class loader, or the class loader 120 * used to load Digester itself, is used, based on the value of the 121 * <code>useContextClassLoader</code> variable. 122 */ 123 protected transient ClassLoader classLoader; 124 125 /** 126 * Whether or not to use the Context ClassLoader when loading classes 127 * for instantiating new objects. Default is {@code false}. 128 */ 129 protected boolean useContextClassLoader; 130 131 /** 132 * Sets this to true to not return Fields that pass validation. Only return failures. 133 */ 134 protected boolean onlyReturnErrors; 135 136 /** 137 * Constructs a <code>Validator</code> that will 138 * use the <code>ValidatorResources</code> 139 * passed in to retrieve pluggable validators 140 * the different sets of validation rules. 141 * 142 * @param resources <code>ValidatorResources</code> to use during validation. 143 */ 144 public Validator(final ValidatorResources resources) { 145 this(resources, null); 146 } 147 148 /** 149 * Constructs a <code>Validator</code> that will 150 * use the <code>ValidatorResources</code> 151 * passed in to retrieve pluggable validators 152 * the different sets of validation rules. 153 * 154 * @param resources <code>ValidatorResources</code> to use during validation. 155 * @param formName Key used for retrieving the set of validation rules. 156 */ 157 public Validator(final ValidatorResources resources, final String formName) { 158 if (resources == null) { 159 throw new IllegalArgumentException("Resources cannot be null."); 160 } 161 162 this.resources = resources; 163 this.formName = formName; 164 } 165 166 /** 167 * Constructs a <code>Validator</code> that will 168 * use the <code>ValidatorResources</code> 169 * passed in to retrieve pluggable validators 170 * the different sets of validation rules. 171 * 172 * @param resources <code>ValidatorResources</code> to use during validation. 173 * @param formName Key used for retrieving the set of validation rules. 174 * @param fieldName Key used for retrieving the set of validation rules for a field 175 * @since 1.2.0 176 */ 177 public Validator(final ValidatorResources resources, final String formName, final String fieldName) { 178 if (resources == null) { 179 throw new IllegalArgumentException("Resources cannot be null."); 180 } 181 182 this.resources = resources; 183 this.formName = formName; 184 this.fieldName = fieldName; 185 } 186 187 /** 188 * Clears the form name, resources that were added, and the page that was 189 * set (if any). This can be called to reinitialize the Validator instance 190 * so it can be reused. The form name (key to set of validation rules) and any 191 * resources needed, like the JavaBean being validated, will need to 192 * set and/or added to this instance again. The 193 * <code>ValidatorResources</code> will not be removed since it can be used 194 * again and is thread safe. 195 */ 196 public void clear() { 197 this.formName = null; 198 this.fieldName = null; 199 this.parameters = new HashMap<>(); 200 this.page = 0; 201 } 202 203 /** 204 * Gets the class loader to be used for instantiating application objects 205 * when required. This is determined based upon the following rules: 206 * <ul> 207 * <li>The class loader set by <code>setClassLoader()</code>, if any</li> 208 * <li>The thread context class loader, if it exists and the 209 * <code>useContextClassLoader</code> property is set to true</li> 210 * <li>The class loader used to load the Digester class itself. 211 * </ul> 212 * @return the class loader. 213 */ 214 public ClassLoader getClassLoader() { 215 if (this.classLoader != null) { 216 return this.classLoader; 217 } 218 219 if (this.useContextClassLoader) { 220 final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); 221 if (contextLoader != null) { 222 return contextLoader; 223 } 224 } 225 226 return this.getClass().getClassLoader(); 227 } 228 229 /** 230 * Gets the form name which is the key to a set of validation rules. 231 * @return the name of the form. 232 */ 233 public String getFormName() { 234 return formName; 235 } 236 237 /** 238 * Returns true if the Validator is only returning Fields that fail validation. 239 * @return whether only failed fields are returned. 240 */ 241 public boolean getOnlyReturnErrors() { 242 return onlyReturnErrors; 243 } 244 245 /** 246 * Gets the page. 247 * 248 * <p> 249 * This in conjunction with the page property of 250 * a {@code Field} can control the processing of fields. If the field's 251 * page is less than or equal to this page value, it will be processed. 252 * </p> 253 * 254 * @return the page number. 255 */ 256 public int getPage() { 257 return page; 258 } 259 260 /** 261 * Returns the value of the specified parameter that will be used during the 262 * processing of validations. 263 * 264 * @param parameterClassName The full class name of the parameter of the 265 * validation method that corresponds to the value/instance passed in with it. 266 * @return value of the specified parameter. 267 */ 268 public Object getParameterValue(final String parameterClassName) { 269 return this.parameters.get(parameterClassName); 270 } 271 272 /** 273 * Gets the boolean as to whether the context classloader should be used. 274 * @return whether the context classloader should be used. 275 */ 276 public boolean getUseContextClassLoader() { 277 return this.useContextClassLoader; 278 } 279 280 /** 281 * Sets the class loader to be used for instantiating application objects 282 * when required. 283 * 284 * @param classLoader The new class loader to use, or {@code null} 285 * to revert to the standard rules 286 */ 287 public void setClassLoader(final ClassLoader classLoader) { 288 this.classLoader = classLoader; 289 } 290 291 /** 292 * Sets the name of the field to validate in a form (optional) 293 * 294 * @param fieldName The name of the field in a form set 295 * @since 1.2.0 296 */ 297 public void setFieldName(final String fieldName) { 298 this.fieldName = fieldName; 299 } 300 301 /** 302 * Sets the form name which is the key to a set of validation rules. 303 * @param formName the name of the form. 304 */ 305 public void setFormName(final String formName) { 306 this.formName = formName; 307 } 308 309 /** 310 * Configures which Fields the Validator returns from the validate() method. Set this 311 * to true to only return Fields that failed validation. By default, validate() returns 312 * all fields. 313 * @param onlyReturnErrors whether only failed fields are returned. 314 */ 315 public void setOnlyReturnErrors(final boolean onlyReturnErrors) { 316 this.onlyReturnErrors = onlyReturnErrors; 317 } 318 319 /** 320 * Sets the page. 321 * <p> 322 * This in conjunction with the page property of 323 * a {@code Field} can control the processing of fields. If the field's page 324 * is less than or equal to this page value, it will be processed. 325 * </p> 326 * 327 * @param page the page number. 328 */ 329 public void setPage(final int page) { 330 this.page = page; 331 } 332 333 /** 334 * Sets a parameter of a pluggable validation method. 335 * 336 * @param parameterClassName The full class name of the parameter of the 337 * validation method that corresponds to the value/instance passed in with it. 338 * 339 * @param parameterValue The instance that will be passed into the 340 * validation method. 341 */ 342 public void setParameter(final String parameterClassName, final Object parameterValue) { 343 this.parameters.put(parameterClassName, parameterValue); 344 } 345 346 /** 347 * Determine whether to use the Context ClassLoader (the one found by 348 * calling <code>Thread.currentThread().getContextClassLoader()</code>) 349 * to resolve/load classes that are defined in various rules. If not 350 * using Context ClassLoader, then the class-loading defaults to 351 * using the calling-class' ClassLoader. 352 * 353 * @param use determines whether to use Context ClassLoader. 354 */ 355 public void setUseContextClassLoader(final boolean use) { 356 this.useContextClassLoader = use; 357 } 358 359 /** 360 * Performs validations based on the configured resources. 361 * 362 * @return The <code>Map</code> returned uses the property of the 363 * <code>Field</code> for the key and the value is the number of error the 364 * field had. 365 * @throws ValidatorException If an error occurs during validation 366 */ 367 public ValidatorResults validate() throws ValidatorException { 368 Locale locale = (Locale) this.getParameterValue(LOCALE_PARAM); 369 370 if (locale == null) { 371 locale = Locale.getDefault(); 372 } 373 374 this.setParameter(VALIDATOR_PARAM, this); 375 376 final Form form = this.resources.getForm(locale, this.formName); 377 if (form != null) { 378 this.setParameter(FORM_PARAM, form); 379 return form.validate( 380 this.parameters, 381 this.resources.getValidatorActions(), 382 this.page, 383 this.fieldName); 384 } 385 386 return new ValidatorResults(); 387 } 388 389}