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 }