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 * https://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} 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 /** 033 * Resources key the JavaBean is stored to perform validation on. 034 */ 035 public static final String BEAN_PARAM = "java.lang.Object"; 036 037 /** 038 * Resources key the {@code Field} is stored under. 039 * This will be automatically passed into a validation method 040 * with the current {@code Field} if it is 041 * specified in the method signature. 042 */ 043 public static final String FIELD_PARAM = "org.apache.commons.validator.Field"; 044 045 /** 046 * Resources key the {@code Form} is stored under. 047 * This will be automatically passed into a validation method 048 * with the current {@code Form} if it is 049 * specified in the method signature. 050 */ 051 public static final String FORM_PARAM = "org.apache.commons.validator.Form"; 052 053 /** 054 * Resources key the {@link Locale} is stored. 055 * This will be used to retrieve the appropriate 056 * {@code FormSet} and {@code Form} to be 057 * processed. 058 */ 059 public static final String LOCALE_PARAM = "java.util.Locale"; 060 061 private static final long serialVersionUID = -7119418755208731611L; 062 063 /** 064 * Resources key the {@code ValidatorAction} is stored under. 065 * This will be automatically passed into a validation method 066 * with the current {@code ValidatorAction} if it is 067 * specified in the method signature. 068 */ 069 public static final String VALIDATOR_ACTION_PARAM = 070 "org.apache.commons.validator.ValidatorAction"; 071 072 /** 073 * Resources key the {@code Validator} is stored under. 074 * This will be automatically passed into a validation method 075 * with the current {@code Validator} if it is 076 * specified in the method signature. 077 */ 078 public static final String VALIDATOR_PARAM = 079 "org.apache.commons.validator.Validator"; 080 081 /** 082 * Resources key the {@code ValidatorResults} is stored under. 083 * This will be automatically passed into a validation method 084 * with the current {@code ValidatorResults} if it is 085 * specified in the method signature. 086 */ 087 public static final String VALIDATOR_RESULTS_PARAM = 088 "org.apache.commons.validator.ValidatorResults"; 089 090 static Locale toLocale(final Locale locale) { 091 return locale != null ? locale : Locale.getDefault(); 092 } 093 094 /** 095 * The class loader to use for instantiating application objects. 096 * If not specified, the context class loader, or the class loader 097 * used to load Digester itself, is used, based on the value of the 098 * {@code useContextClassLoader} variable. 099 * 100 * @deprecated Use {@link #getClassLoader()}, will be private in the next major version. 101 */ 102 @Deprecated 103 protected transient ClassLoader classLoader; 104 105 /** 106 * The name of the field on the form to validate 107 * 108 * @since 1.2.0 109 * 110 * @deprecated Use {@link #getFieldName()}, will be private in the next major version. 111 */ 112 @Deprecated 113 protected String fieldName; 114 115 /** 116 * The name of the form to validate 117 * 118 * @deprecated Use {@link #getFormName()}, will be private in the next major version. 119 */ 120 @Deprecated 121 protected String formName; 122 123 /** 124 * Sets this to true to not return Fields that pass validation. Only return failures. 125 * 126 * @deprecated Use {@link #getOnlyReturnErrors()}, will be private in the next major version. 127 */ 128 @Deprecated 129 protected boolean onlyReturnErrors; 130 131 /** 132 * The current page number to validate. 133 * 134 * @deprecated Use {@link #getPage()}, will be private in the next major version. 135 */ 136 @Deprecated 137 protected int page; 138 139 /** 140 * Maps validation method parameter class names to the objects to be passed 141 * into the method. 142 * 143 * @deprecated Use {@link #getParameters()}, will be private in the next major version. 144 */ 145 @Deprecated 146 protected Map<String, Object> parameters = new HashMap<>(); 147 148 /** 149 * The Validator Resources. 150 * 151 * @deprecated Use {@link #getResources()}, will be private in the next major version. 152 */ 153 @Deprecated 154 protected ValidatorResources resources; 155 156 /** 157 * Whether or not to use the Context ClassLoader when loading classes 158 * for instantiating new objects. Default is {@code false}. 159 * 160 * @deprecated Use {@link #getUseContextClassLoader()}, will be private in the next major version. 161 */ 162 @Deprecated 163 protected boolean useContextClassLoader; 164 165 /** 166 * Constructs a {@code Validator} that will 167 * use the {@code ValidatorResources} 168 * passed in to retrieve pluggable validators 169 * the different sets of validation rules. 170 * 171 * @param resources {@code ValidatorResources} to use during validation. 172 */ 173 public Validator(final ValidatorResources resources) { 174 this(resources, null); 175 } 176 177 /** 178 * Constructs a {@code Validator} that will 179 * use the {@code ValidatorResources} 180 * passed in to retrieve pluggable validators 181 * the different sets of validation rules. 182 * 183 * @param resources {@code ValidatorResources} to use during validation. 184 * @param formName Key used for retrieving the set of validation rules. 185 */ 186 public Validator(final ValidatorResources resources, final String formName) { 187 if (resources == null) { 188 throw new IllegalArgumentException("Resources cannot be null."); 189 } 190 191 this.resources = resources; 192 this.formName = formName; 193 } 194 195 /** 196 * Constructs a {@code Validator} that will 197 * use the {@code ValidatorResources} 198 * passed in to retrieve pluggable validators 199 * the different sets of validation rules. 200 * 201 * @param resources {@code ValidatorResources} to use during validation. 202 * @param formName Key used for retrieving the set of validation rules. 203 * @param fieldName Key used for retrieving the set of validation rules for a field 204 * @since 1.2.0 205 */ 206 public Validator(final ValidatorResources resources, final String formName, final String fieldName) { 207 if (resources == null) { 208 throw new IllegalArgumentException("Resources cannot be null."); 209 } 210 211 this.resources = resources; 212 this.formName = formName; 213 this.fieldName = fieldName; 214 } 215 216 /** 217 * Clears the form name, resources that were added, and the page that was 218 * set (if any). This can be called to reinitialize the Validator instance 219 * so it can be reused. The form name (key to set of validation rules) and any 220 * resources needed, like the JavaBean being validated, will need to 221 * set and/or added to this instance again. The 222 * {@code ValidatorResources} will not be removed since it can be used 223 * again and is thread safe. 224 */ 225 public void clear() { 226 formName = null; 227 fieldName = null; 228 parameters.clear(); 229 page = 0; 230 } 231 232 /** 233 * Gets the class loader to be used for instantiating application objects 234 * when required. This is determined based upon the following rules: 235 * <ul> 236 * <li>The class loader set by {@code setClassLoader()}, if any</li> 237 * <li>The thread context class loader, if it exists and the 238 * {@code useContextClassLoader} property is set to true</li> 239 * <li>The class loader used to load the Digester class itself.</li> 240 * </ul> 241 * 242 * @return The class loader. 243 */ 244 public ClassLoader getClassLoader() { 245 if (classLoader != null) { 246 return classLoader; 247 } 248 249 if (useContextClassLoader) { 250 final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); 251 if (contextLoader != null) { 252 return contextLoader; 253 } 254 } 255 256 return this.getClass().getClassLoader(); 257 } 258 259 /** 260 * Gets the field name. 261 * 262 * @return The field name. 263 * @since 1.10.0 264 */ 265 public String getFieldName() { 266 return fieldName; 267 } 268 269 /** 270 * Gets the form name which is the key to a set of validation rules. 271 * 272 * @return The name of the form. 273 */ 274 public String getFormName() { 275 return formName; 276 } 277 278 /** 279 * Returns true if the Validator is only returning Fields that fail validation. 280 * 281 * @return whether only failed fields are returned. 282 */ 283 public boolean getOnlyReturnErrors() { 284 return onlyReturnErrors; 285 } 286 287 /** 288 * Gets the page. 289 * 290 * <p> 291 * This in conjunction with the page property of 292 * a {@code Field} can control the processing of fields. If the field's 293 * page is less than or equal to this page value, it will be processed. 294 * </p> 295 * 296 * @return The page number. 297 */ 298 public int getPage() { 299 return page; 300 } 301 302 /** 303 * Gets the parameter map. 304 * 305 * @return The parameter map. 306 * @since 1.10.0 307 */ 308 public Map<String, Object> getParameters() { 309 return parameters; 310 } 311 312 /** 313 * Returns the value of the specified parameter that will be used during the 314 * processing of validations. 315 * 316 * @param parameterClassName The full class name of the parameter of the 317 * validation method that corresponds to the value/instance passed in with it. 318 * @return value of the specified parameter. 319 */ 320 public Object getParameterValue(final String parameterClassName) { 321 return parameters.get(parameterClassName); 322 } 323 324 /** 325 * Gets the validator resource. 326 * 327 * @return The validator resource. 328 * @since 1.10.0 329 */ 330 public ValidatorResources getResources() { 331 return resources; 332 } 333 334 /** 335 * Gets the boolean as to whether the context classloader should be used. 336 * 337 * @return whether the context classloader should be used. 338 */ 339 public boolean getUseContextClassLoader() { 340 return useContextClassLoader; 341 } 342 343 /** 344 * Sets the class loader to be used for instantiating application objects 345 * when required. 346 * 347 * @param classLoader The new class loader to use, or {@code null} 348 * to revert to the standard rules 349 */ 350 public void setClassLoader(final ClassLoader classLoader) { 351 this.classLoader = classLoader; 352 } 353 354 /** 355 * Sets the name of the field to validate in a form (optional) 356 * 357 * @param fieldName The name of the field in a form set 358 * @since 1.2.0 359 */ 360 public void setFieldName(final String fieldName) { 361 this.fieldName = fieldName; 362 } 363 364 /** 365 * Sets the form name which is the key to a set of validation rules. 366 * 367 * @param formName The name of the form. 368 */ 369 public void setFormName(final String formName) { 370 this.formName = formName; 371 } 372 373 /** 374 * Configures which Fields the Validator returns from the validate() method. Set this 375 * to true to only return Fields that failed validation. By default, validate() returns 376 * all fields. 377 * 378 * @param onlyReturnErrors whether only failed fields are returned. 379 */ 380 public void setOnlyReturnErrors(final boolean onlyReturnErrors) { 381 this.onlyReturnErrors = onlyReturnErrors; 382 } 383 384 /** 385 * Sets the page. 386 * <p> 387 * This in conjunction with the page property of 388 * a {@code Field} can control the processing of fields. If the field's page 389 * is less than or equal to this page value, it will be processed. 390 * </p> 391 * 392 * @param page The page number. 393 */ 394 public void setPage(final int page) { 395 this.page = page; 396 } 397 398 /** 399 * Sets a parameter of a pluggable validation method. 400 * 401 * @param parameterClassName The full class name of the parameter of the 402 * validation method that corresponds to the value/instance passed in with it. 403 * 404 * @param parameterValue The instance that will be passed into the 405 * validation method. 406 */ 407 public void setParameter(final String parameterClassName, final Object parameterValue) { 408 parameters.put(parameterClassName, parameterValue); 409 } 410 411 /** 412 * Sets whether to use the Context ClassLoader (the one found by 413 * calling {@code Thread.currentThread().getContextClassLoader()}) 414 * to resolve/load classes that are defined in various rules. If not 415 * using Context ClassLoader, then the class-loading defaults to 416 * using the calling-class' ClassLoader. 417 * 418 * @param useContextClassLoader determines whether to use Context ClassLoader. 419 */ 420 public void setUseContextClassLoader(final boolean useContextClassLoader) { 421 this.useContextClassLoader = useContextClassLoader; 422 } 423 424 /** 425 * Performs validations based on the configured resources. 426 * 427 * @return The {@link Map} returned uses the property of the 428 * {@code Field} for the key and the value is the number of error the 429 * field had. 430 * @throws ValidatorException If an error occurs during validation 431 */ 432 public ValidatorResults validate() throws ValidatorException { 433 Locale locale = (Locale) getParameterValue(LOCALE_PARAM); 434 locale = toLocale(locale); 435 setParameter(VALIDATOR_PARAM, this); 436 final Form form = resources.getForm(locale, formName); 437 if (form != null) { 438 setParameter(FORM_PARAM, form); 439 return form.validate(parameters, resources.getValidatorActions(), page, fieldName); 440 } 441 return new ValidatorResults(); 442 } 443 444}