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.
236      * </ul>
237      * @return the class loader.
238      */
239     public ClassLoader getClassLoader() {
240         if (classLoader != null) {
241             return classLoader;
242         }
243 
244         if (useContextClassLoader) {
245             final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
246             if (contextLoader != null) {
247                 return contextLoader;
248             }
249         }
250 
251         return this.getClass().getClassLoader();
252     }
253 
254     /**
255      * Gets the field name.
256      *
257      * @return the field name.
258      * @since 1.10.0
259      */
260     public String getFieldName() {
261         return fieldName;
262     }
263 
264     /**
265      * Gets the form name which is the key to a set of validation rules.
266      * @return the name of the form.
267      */
268     public String getFormName() {
269         return formName;
270     }
271 
272     /**
273      * Returns true if the Validator is only returning Fields that fail validation.
274      * @return whether only failed fields are returned.
275      */
276     public boolean getOnlyReturnErrors() {
277         return onlyReturnErrors;
278     }
279 
280     /**
281      * Gets the page.
282      *
283      * <p>
284      * This in conjunction with the page property of
285      * a {@code Field} can control the processing of fields. If the field's
286      * page is less than or equal to this page value, it will be processed.
287      * </p>
288      *
289      * @return the page number.
290      */
291     public int getPage() {
292         return page;
293     }
294 
295     /**
296      * Gets the parameter map.
297      *
298      * @return the parameter map.
299      * @since 1.10.0
300      */
301     public Map<String, Object> getParameters() {
302         return parameters;
303     }
304 
305     /**
306      * Returns the value of the specified parameter that will be used during the
307      * processing of validations.
308      *
309      * @param parameterClassName The full class name of the parameter of the
310      * validation method that corresponds to the value/instance passed in with it.
311      * @return value of the specified parameter.
312      */
313     public Object getParameterValue(final String parameterClassName) {
314         return parameters.get(parameterClassName);
315     }
316 
317     /**
318      * Gets the validator resource.
319      *
320      * @return the validator resource.
321      * @since 1.10.0
322      */
323     public ValidatorResources getResources() {
324         return resources;
325     }
326 
327     /**
328      * Gets the boolean as to whether the context classloader should be used.
329      * @return whether the context classloader should be used.
330      */
331     public boolean getUseContextClassLoader() {
332         return useContextClassLoader;
333     }
334 
335     /**
336      * Sets the class loader to be used for instantiating application objects
337      * when required.
338      *
339      * @param classLoader The new class loader to use, or {@code null}
340      *  to revert to the standard rules
341      */
342     public void setClassLoader(final ClassLoader classLoader) {
343         this.classLoader = classLoader;
344     }
345 
346     /**
347      * Sets the name of the field to validate in a form (optional)
348      *
349      * @param fieldName The name of the field in a form set
350      * @since 1.2.0
351      */
352     public void setFieldName(final String fieldName) {
353         this.fieldName = fieldName;
354     }
355 
356     /**
357      * Sets the form name which is the key to a set of validation rules.
358      * @param formName the name of the form.
359      */
360     public void setFormName(final String formName) {
361         this.formName = formName;
362     }
363 
364     /**
365      * Configures which Fields the Validator returns from the validate() method.  Set this
366      * to true to only return Fields that failed validation.  By default, validate() returns
367      * all fields.
368      * @param onlyReturnErrors whether only failed fields are returned.
369      */
370     public void setOnlyReturnErrors(final boolean onlyReturnErrors) {
371         this.onlyReturnErrors = onlyReturnErrors;
372     }
373 
374     /**
375      * Sets the page.
376      * <p>
377      * This in conjunction with the page property of
378      * a {@code Field} can control the processing of fields. If the field's page
379      * is less than or equal to this page value, it will be processed.
380      * </p>
381      *
382      * @param page the page number.
383      */
384     public void setPage(final int page) {
385         this.page = page;
386     }
387 
388     /**
389      * Sets a parameter of a pluggable validation method.
390      *
391      * @param parameterClassName The full class name of the parameter of the
392      * validation method that corresponds to the value/instance passed in with it.
393      *
394      * @param parameterValue The instance that will be passed into the
395      * validation method.
396      */
397     public void setParameter(final String parameterClassName, final Object parameterValue) {
398         parameters.put(parameterClassName, parameterValue);
399     }
400 
401     /**
402      * Sets whether to use the Context ClassLoader (the one found by
403      * calling {@code Thread.currentThread().getContextClassLoader()})
404      * to resolve/load classes that are defined in various rules.  If not
405      * using Context ClassLoader, then the class-loading defaults to
406      * using the calling-class' ClassLoader.
407      *
408      * @param useContextClassLoader determines whether to use Context ClassLoader.
409      */
410     public void setUseContextClassLoader(final boolean useContextClassLoader) {
411         this.useContextClassLoader = useContextClassLoader;
412     }
413 
414     /**
415      * Performs validations based on the configured resources.
416      *
417      * @return The {@link Map} returned uses the property of the
418      * {@code Field} for the key and the value is the number of error the
419      * field had.
420      * @throws ValidatorException If an error occurs during validation
421      */
422     public ValidatorResults validate() throws ValidatorException {
423         Locale locale = (Locale) getParameterValue(LOCALE_PARAM);
424 
425         if (locale == null) {
426             locale = Locale.getDefault();
427         }
428 
429         setParameter(VALIDATOR_PARAM, this);
430 
431         final Form form = resources.getForm(locale, formName);
432         if (form != null) {
433             setParameter(FORM_PARAM, form);
434             return form.validate(
435                 parameters,
436                 resources.getValidatorActions(),
437                 page,
438                 fieldName);
439         }
440 
441         return new ValidatorResults();
442     }
443 
444 }