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 }