View Javadoc
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    *      https://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.Serializable;
20  import java.util.HashMap;
21  import java.util.Locale;
22  import java.util.Map;
23  
24  /**
25   * Validations are processed by the validate method. An instance of
26   * {@code ValidatorResources} is used to define the validators
27   * (validation methods) and the validation rules for a JavaBean.
28   */
29  // TODO mutable fields should be made private and accessed via suitable methods only
30  public class Validator implements Serializable {
31  
32      private static final long serialVersionUID = -7119418755208731611L;
33  
34      /**
35       * Resources key the JavaBean is stored to perform validation on.
36       */
37      public static final String BEAN_PARAM = "java.lang.Object";
38  
39      /**
40       * Resources key the {@code ValidatorAction} is stored under.
41       * This will be automatically passed into a validation method
42       * with the current {@code ValidatorAction} if it is
43       * specified in the method signature.
44       */
45      public static final String VALIDATOR_ACTION_PARAM =
46              "org.apache.commons.validator.ValidatorAction";
47  
48      /**
49       * Resources key the {@code ValidatorResults} is stored under.
50       * This will be automatically passed into a validation method
51       * with the current {@code ValidatorResults} if it is
52       * specified in the method signature.
53       */
54      public static final String VALIDATOR_RESULTS_PARAM =
55              "org.apache.commons.validator.ValidatorResults";
56  
57      /**
58       * Resources key the {@code Form} is stored under.
59       * This will be automatically passed into a validation method
60       * with the current {@code Form} if it is
61       * specified in the method signature.
62       */
63      public static final String FORM_PARAM = "org.apache.commons.validator.Form";
64  
65      /**
66       * Resources key the {@code Field} is stored under.
67       * This will be automatically passed into a validation method
68       * with the current {@code Field} if it is
69       * specified in the method signature.
70       */
71      public static final String FIELD_PARAM = "org.apache.commons.validator.Field";
72  
73      /**
74       * Resources key the {@code Validator} is stored under.
75       * This will be automatically passed into a validation method
76       * with the current {@code Validator} if it is
77       * specified in the method signature.
78       */
79      public static final String VALIDATOR_PARAM =
80              "org.apache.commons.validator.Validator";
81  
82      /**
83       * Resources key the {@link Locale} is stored.
84       * This will be used to retrieve the appropriate
85       * {@code FormSet} and {@code Form} to be
86       * processed.
87       */
88      public static final String LOCALE_PARAM = "java.util.Locale";
89  
90      /**
91       * The Validator Resources.
92       *
93       * @deprecated Use {@link #getResources()}, will be private in the next major version.
94       */
95      @Deprecated
96      protected ValidatorResources resources;
97  
98      /**
99       * The name of the form to validate
100      *
101      * @deprecated Use {@link #getFormName()}, will be private in the next major version.
102      */
103     @Deprecated
104     protected String formName;
105 
106     /**
107      * The name of the field on the form to validate
108      *
109      * @since 1.2.0
110      *
111      * @deprecated Use {@link #getFieldName()}, will be private in the next major version.
112      */
113     @Deprecated
114     protected String fieldName;
115 
116     /**
117      * Maps validation method parameter class names to the objects to be passed
118      * into the method.
119      *
120      * @deprecated Use {@link #getParameters()}, will be private in the next major version.
121      */
122     @Deprecated
123     protected Map<String, Object> parameters = new HashMap<>();
124 
125     /**
126      * The current page number to validate.
127      *
128      * @deprecated Use {@link #getPage()}, will be private in the next major version.
129      */
130     @Deprecated
131     protected int page;
132 
133     /**
134      * The class loader to use for instantiating application objects.
135      * If not specified, the context class loader, or the class loader
136      * used to load Digester itself, is used, based on the value of the
137      * {@code useContextClassLoader} variable.
138      *
139      * @deprecated Use {@link #getClassLoader()}, will be private in the next major version.
140      */
141     @Deprecated
142     protected transient ClassLoader classLoader;
143 
144     /**
145      * Whether or not to use the Context ClassLoader when loading classes
146      * for instantiating new objects.  Default is {@code false}.
147      *
148      * @deprecated Use {@link #getUseContextClassLoader()}, will be private in the next major version.
149      */
150     @Deprecated
151     protected boolean useContextClassLoader;
152 
153     /**
154      * Sets this to true to not return Fields that pass validation.  Only return failures.
155      *
156      * @deprecated Use {@link #getOnlyReturnErrors()}, will be private in the next major version.
157      */
158     @Deprecated
159     protected boolean onlyReturnErrors;
160 
161     /**
162      * Constructs a {@code Validator} that will
163      * use the {@code ValidatorResources}
164      * passed in to retrieve pluggable validators
165      * the different sets of validation rules.
166      *
167      * @param resources {@code ValidatorResources} to use during validation.
168      */
169     public Validator(final ValidatorResources resources) {
170         this(resources, null);
171     }
172 
173     /**
174      * Constructs a {@code Validator} that will
175      * use the {@code ValidatorResources}
176      * passed in to retrieve pluggable validators
177      * the different sets of validation rules.
178      *
179      * @param resources {@code ValidatorResources} to use during validation.
180      * @param formName Key used for retrieving the set of validation rules.
181      */
182     public Validator(final ValidatorResources resources, final String formName) {
183         if (resources == null) {
184             throw new IllegalArgumentException("Resources cannot be null.");
185         }
186 
187         this.resources = resources;
188         this.formName = formName;
189     }
190 
191     /**
192      * Constructs a {@code Validator} that will
193      * use the {@code ValidatorResources}
194      * passed in to retrieve pluggable validators
195      * the different sets of validation rules.
196      *
197      * @param resources {@code ValidatorResources} to use during validation.
198      * @param formName Key used for retrieving the set of validation rules.
199      * @param fieldName Key used for retrieving the set of validation rules for a field
200      * @since 1.2.0
201      */
202     public Validator(final ValidatorResources resources, final String formName, final String fieldName) {
203         if (resources == null) {
204             throw new IllegalArgumentException("Resources cannot be null.");
205         }
206 
207         this.resources = resources;
208         this.formName = formName;
209         this.fieldName = fieldName;
210     }
211 
212     /**
213      * Clears the form name, resources that were added, and the page that was
214      * set (if any).  This can be called to reinitialize the Validator instance
215      * so it can be reused.  The form name (key to set of validation rules) and any
216      * resources needed, like the JavaBean being validated, will need to
217      * set and/or added to this instance again.  The
218      * {@code ValidatorResources} will not be removed since it can be used
219      * again and is thread safe.
220      */
221     public void clear() {
222         formName = null;
223         fieldName = null;
224         parameters.clear();
225         page = 0;
226     }
227 
228     /**
229      * Gets the class loader to be used for instantiating application objects
230      * when required.  This is determined based upon the following rules:
231      * <ul>
232      * <li>The class loader set by {@code setClassLoader()}, if any</li>
233      * <li>The thread context class loader, if it exists and the
234      *     {@code useContextClassLoader} property is set to true</li>
235      * <li>The class loader used to load the Digester class itself.</li>
236      * </ul>
237      *
238      * @return the class loader.
239      */
240     public ClassLoader getClassLoader() {
241         if (classLoader != null) {
242             return classLoader;
243         }
244 
245         if (useContextClassLoader) {
246             final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
247             if (contextLoader != null) {
248                 return contextLoader;
249             }
250         }
251 
252         return this.getClass().getClassLoader();
253     }
254 
255     /**
256      * Gets the field name.
257      *
258      * @return the field name.
259      * @since 1.10.0
260      */
261     public String getFieldName() {
262         return fieldName;
263     }
264 
265     /**
266      * Gets the form name which is the key to a set of validation rules.
267      *
268      * @return the name of the form.
269      */
270     public String getFormName() {
271         return formName;
272     }
273 
274     /**
275      * Returns true if the Validator is only returning Fields that fail validation.
276      *
277      * @return whether only failed fields are returned.
278      */
279     public boolean getOnlyReturnErrors() {
280         return onlyReturnErrors;
281     }
282 
283     /**
284      * Gets the page.
285      *
286      * <p>
287      * This in conjunction with the page property of
288      * a {@code Field} can control the processing of fields. If the field's
289      * page is less than or equal to this page value, it will be processed.
290      * </p>
291      *
292      * @return the page number.
293      */
294     public int getPage() {
295         return page;
296     }
297 
298     /**
299      * Gets the parameter map.
300      *
301      * @return the parameter map.
302      * @since 1.10.0
303      */
304     public Map<String, Object> getParameters() {
305         return parameters;
306     }
307 
308     /**
309      * Returns the value of the specified parameter that will be used during the
310      * processing of validations.
311      *
312      * @param parameterClassName The full class name of the parameter of the
313      * validation method that corresponds to the value/instance passed in with it.
314      * @return value of the specified parameter.
315      */
316     public Object getParameterValue(final String parameterClassName) {
317         return parameters.get(parameterClassName);
318     }
319 
320     /**
321      * Gets the validator resource.
322      *
323      * @return the validator resource.
324      * @since 1.10.0
325      */
326     public ValidatorResources getResources() {
327         return resources;
328     }
329 
330     /**
331      * Gets the boolean as to whether the context classloader should be used.
332      *
333      * @return whether the context classloader should be used.
334      */
335     public boolean getUseContextClassLoader() {
336         return useContextClassLoader;
337     }
338 
339     /**
340      * Sets the class loader to be used for instantiating application objects
341      * when required.
342      *
343      * @param classLoader The new class loader to use, or {@code null}
344      *  to revert to the standard rules
345      */
346     public void setClassLoader(final ClassLoader classLoader) {
347         this.classLoader = classLoader;
348     }
349 
350     /**
351      * Sets the name of the field to validate in a form (optional)
352      *
353      * @param fieldName The name of the field in a form set
354      * @since 1.2.0
355      */
356     public void setFieldName(final String fieldName) {
357         this.fieldName = fieldName;
358     }
359 
360     /**
361      * Sets the form name which is the key to a set of validation rules.
362      *
363      * @param formName the name of the form.
364      */
365     public void setFormName(final String formName) {
366         this.formName = formName;
367     }
368 
369     /**
370      * Configures which Fields the Validator returns from the validate() method.  Set this
371      * to true to only return Fields that failed validation.  By default, validate() returns
372      * all fields.
373      *
374      * @param onlyReturnErrors whether only failed fields are returned.
375      */
376     public void setOnlyReturnErrors(final boolean onlyReturnErrors) {
377         this.onlyReturnErrors = onlyReturnErrors;
378     }
379 
380     /**
381      * Sets the page.
382      * <p>
383      * This in conjunction with the page property of
384      * a {@code Field} can control the processing of fields. If the field's page
385      * is less than or equal to this page value, it will be processed.
386      * </p>
387      *
388      * @param page the page number.
389      */
390     public void setPage(final int page) {
391         this.page = page;
392     }
393 
394     /**
395      * Sets a parameter of a pluggable validation method.
396      *
397      * @param parameterClassName The full class name of the parameter of the
398      * validation method that corresponds to the value/instance passed in with it.
399      *
400      * @param parameterValue The instance that will be passed into the
401      * validation method.
402      */
403     public void setParameter(final String parameterClassName, final Object parameterValue) {
404         parameters.put(parameterClassName, parameterValue);
405     }
406 
407     /**
408      * Sets whether to use the Context ClassLoader (the one found by
409      * calling {@code Thread.currentThread().getContextClassLoader()})
410      * to resolve/load classes that are defined in various rules.  If not
411      * using Context ClassLoader, then the class-loading defaults to
412      * using the calling-class' ClassLoader.
413      *
414      * @param useContextClassLoader determines whether to use Context ClassLoader.
415      */
416     public void setUseContextClassLoader(final boolean useContextClassLoader) {
417         this.useContextClassLoader = useContextClassLoader;
418     }
419 
420     /**
421      * Performs validations based on the configured resources.
422      *
423      * @return The {@link Map} returned uses the property of the
424      * {@code Field} for the key and the value is the number of error the
425      * field had.
426      * @throws ValidatorException If an error occurs during validation
427      */
428     public ValidatorResults validate() throws ValidatorException {
429         Locale locale = (Locale) getParameterValue(LOCALE_PARAM);
430 
431         if (locale == null) {
432             locale = Locale.getDefault();
433         }
434 
435         setParameter(VALIDATOR_PARAM, this);
436 
437         final Form form = resources.getForm(locale, formName);
438         if (form != null) {
439             setParameter(FORM_PARAM, form);
440             return form.validate(
441                 parameters,
442                 resources.getValidatorActions(),
443                 page,
444                 fieldName);
445         }
446 
447         return new ValidatorResults();
448     }
449 
450 }