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    *      http://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</code> 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</code> is stored under.
41       * This will be automatically passed into a validation method
42       * with the current <code>ValidatorAction</code> 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</code> is stored under.
50       * This will be automatically passed into a validation method
51       * with the current <code>ValidatorResults</code> 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</code> is stored under.
59       * This will be automatically passed into a validation method
60       * with the current <code>Form</code> 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</code> is stored under.
67       * This will be automatically passed into a validation method
68       * with the current <code>Field</code> 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</code> is stored under.
75       * This will be automatically passed into a validation method
76       * with the current <code>Validator</code> 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 <code>Locale</code> is stored.
84       * This will be used to retrieve the appropriate
85       * <code>FormSet</code> and <code>Form</code> to be
86       * processed.
87       */
88      public static final String LOCALE_PARAM = "java.util.Locale";
89  
90      /**
91       * The Validator Resources.
92       */
93      protected ValidatorResources resources;
94  
95      /**
96       * The name of the form to validate
97       */
98      protected String formName;
99  
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 }