001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.validation;
018
019import java.beans.PropertyEditor;
020import java.lang.reflect.Field;
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030
031import org.springframework.beans.ConfigurablePropertyAccessor;
032import org.springframework.beans.MutablePropertyValues;
033import org.springframework.beans.PropertyAccessException;
034import org.springframework.beans.PropertyAccessorUtils;
035import org.springframework.beans.PropertyBatchUpdateException;
036import org.springframework.beans.PropertyEditorRegistry;
037import org.springframework.beans.PropertyValue;
038import org.springframework.beans.PropertyValues;
039import org.springframework.beans.SimpleTypeConverter;
040import org.springframework.beans.TypeConverter;
041import org.springframework.beans.TypeMismatchException;
042import org.springframework.core.MethodParameter;
043import org.springframework.core.convert.ConversionService;
044import org.springframework.core.convert.TypeDescriptor;
045import org.springframework.format.Formatter;
046import org.springframework.format.support.FormatterPropertyEditorAdapter;
047import org.springframework.lang.Nullable;
048import org.springframework.util.Assert;
049import org.springframework.util.ObjectUtils;
050import org.springframework.util.PatternMatchUtils;
051import org.springframework.util.StringUtils;
052
053/**
054 * Binder that allows for setting property values onto a target object,
055 * including support for validation and binding result analysis.
056 * The binding process can be customized through specifying allowed fields,
057 * required fields, custom editors, etc.
058 *
059 * <p>Note that there are potential security implications in failing to set an array
060 * of allowed fields. In the case of HTTP form POST data for example, malicious clients
061 * can attempt to subvert an application by supplying values for fields or properties
062 * that do not exist on the form. In some cases this could lead to illegal data being
063 * set on command objects <i>or their nested objects</i>. For this reason, it is
064 * <b>highly recommended to specify the {@link #setAllowedFields allowedFields} property</b>
065 * on the DataBinder.
066 *
067 * <p>The binding results can be examined via the {@link BindingResult} interface,
068 * extending the {@link Errors} interface: see the {@link #getBindingResult()} method.
069 * Missing fields and property access exceptions will be converted to {@link FieldError FieldErrors},
070 * collected in the Errors instance, using the following error codes:
071 *
072 * <ul>
073 * <li>Missing field error: "required"
074 * <li>Type mismatch error: "typeMismatch"
075 * <li>Method invocation error: "methodInvocation"
076 * </ul>
077 *
078 * <p>By default, binding errors get resolved through the {@link BindingErrorProcessor}
079 * strategy, processing for missing fields and property access exceptions: see the
080 * {@link #setBindingErrorProcessor} method. You can override the default strategy
081 * if needed, for example to generate different error codes.
082 *
083 * <p>Custom validation errors can be added afterwards. You will typically want to resolve
084 * such error codes into proper user-visible error messages; this can be achieved through
085 * resolving each error via a {@link org.springframework.context.MessageSource}, which is
086 * able to resolve an {@link ObjectError}/{@link FieldError} through its
087 * {@link org.springframework.context.MessageSource#getMessage(org.springframework.context.MessageSourceResolvable, java.util.Locale)}
088 * method. The list of message codes can be customized through the {@link MessageCodesResolver}
089 * strategy: see the {@link #setMessageCodesResolver} method. {@link DefaultMessageCodesResolver}'s
090 * javadoc states details on the default resolution rules.
091 *
092 * <p>This generic data binder can be used in any kind of environment.
093 *
094 * @author Rod Johnson
095 * @author Juergen Hoeller
096 * @author Rob Harrop
097 * @author Stephane Nicoll
098 * @author Kazuki Shimizu
099 * @see #setAllowedFields
100 * @see #setRequiredFields
101 * @see #registerCustomEditor
102 * @see #setMessageCodesResolver
103 * @see #setBindingErrorProcessor
104 * @see #bind
105 * @see #getBindingResult
106 * @see DefaultMessageCodesResolver
107 * @see DefaultBindingErrorProcessor
108 * @see org.springframework.context.MessageSource
109 */
110public class DataBinder implements PropertyEditorRegistry, TypeConverter {
111
112        /** Default object name used for binding: "target". */
113        public static final String DEFAULT_OBJECT_NAME = "target";
114
115        /** Default limit for array and collection growing: 256. */
116        public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
117
118
119        /**
120         * We'll create a lot of DataBinder instances: Let's use a static logger.
121         */
122        protected static final Log logger = LogFactory.getLog(DataBinder.class);
123
124        @Nullable
125        private final Object target;
126
127        private final String objectName;
128
129        @Nullable
130        private AbstractPropertyBindingResult bindingResult;
131
132        @Nullable
133        private SimpleTypeConverter typeConverter;
134
135        private boolean ignoreUnknownFields = true;
136
137        private boolean ignoreInvalidFields = false;
138
139        private boolean autoGrowNestedPaths = true;
140
141        private int autoGrowCollectionLimit = DEFAULT_AUTO_GROW_COLLECTION_LIMIT;
142
143        @Nullable
144        private String[] allowedFields;
145
146        @Nullable
147        private String[] disallowedFields;
148
149        @Nullable
150        private String[] requiredFields;
151
152        @Nullable
153        private ConversionService conversionService;
154
155        @Nullable
156        private MessageCodesResolver messageCodesResolver;
157
158        private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
159
160        private final List<Validator> validators = new ArrayList<>();
161
162
163        /**
164         * Create a new DataBinder instance, with default object name.
165         * @param target the target object to bind onto (or {@code null}
166         * if the binder is just used to convert a plain parameter value)
167         * @see #DEFAULT_OBJECT_NAME
168         */
169        public DataBinder(@Nullable Object target) {
170                this(target, DEFAULT_OBJECT_NAME);
171        }
172
173        /**
174         * Create a new DataBinder instance.
175         * @param target the target object to bind onto (or {@code null}
176         * if the binder is just used to convert a plain parameter value)
177         * @param objectName the name of the target object
178         */
179        public DataBinder(@Nullable Object target, String objectName) {
180                this.target = ObjectUtils.unwrapOptional(target);
181                this.objectName = objectName;
182        }
183
184
185        /**
186         * Return the wrapped target object.
187         */
188        @Nullable
189        public Object getTarget() {
190                return this.target;
191        }
192
193        /**
194         * Return the name of the bound object.
195         */
196        public String getObjectName() {
197                return this.objectName;
198        }
199
200        /**
201         * Set whether this binder should attempt to "auto-grow" a nested path that contains a null value.
202         * <p>If "true", a null path location will be populated with a default object value and traversed
203         * instead of resulting in an exception. This flag also enables auto-growth of collection elements
204         * when accessing an out-of-bounds index.
205         * <p>Default is "true" on a standard DataBinder. Note that since Spring 4.1 this feature is supported
206         * for bean property access (DataBinder's default mode) and field access.
207         * @see #initBeanPropertyAccess()
208         * @see org.springframework.beans.BeanWrapper#setAutoGrowNestedPaths
209         */
210        public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
211                Assert.state(this.bindingResult == null,
212                                "DataBinder is already initialized - call setAutoGrowNestedPaths before other configuration methods");
213                this.autoGrowNestedPaths = autoGrowNestedPaths;
214        }
215
216        /**
217         * Return whether "auto-growing" of nested paths has been activated.
218         */
219        public boolean isAutoGrowNestedPaths() {
220                return this.autoGrowNestedPaths;
221        }
222
223        /**
224         * Specify the limit for array and collection auto-growing.
225         * <p>Default is 256, preventing OutOfMemoryErrors in case of large indexes.
226         * Raise this limit if your auto-growing needs are unusually high.
227         * @see #initBeanPropertyAccess()
228         * @see org.springframework.beans.BeanWrapper#setAutoGrowCollectionLimit
229         */
230        public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
231                Assert.state(this.bindingResult == null,
232                                "DataBinder is already initialized - call setAutoGrowCollectionLimit before other configuration methods");
233                this.autoGrowCollectionLimit = autoGrowCollectionLimit;
234        }
235
236        /**
237         * Return the current limit for array and collection auto-growing.
238         */
239        public int getAutoGrowCollectionLimit() {
240                return this.autoGrowCollectionLimit;
241        }
242
243        /**
244         * Initialize standard JavaBean property access for this DataBinder.
245         * <p>This is the default; an explicit call just leads to eager initialization.
246         * @see #initDirectFieldAccess()
247         * @see #createBeanPropertyBindingResult()
248         */
249        public void initBeanPropertyAccess() {
250                Assert.state(this.bindingResult == null,
251                                "DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
252                this.bindingResult = createBeanPropertyBindingResult();
253        }
254
255        /**
256         * Create the {@link AbstractPropertyBindingResult} instance using standard
257         * JavaBean property access.
258         * @since 4.2.1
259         */
260        protected AbstractPropertyBindingResult createBeanPropertyBindingResult() {
261                BeanPropertyBindingResult result = new BeanPropertyBindingResult(getTarget(),
262                                getObjectName(), isAutoGrowNestedPaths(), getAutoGrowCollectionLimit());
263
264                if (this.conversionService != null) {
265                        result.initConversion(this.conversionService);
266                }
267                if (this.messageCodesResolver != null) {
268                        result.setMessageCodesResolver(this.messageCodesResolver);
269                }
270
271                return result;
272        }
273
274        /**
275         * Initialize direct field access for this DataBinder,
276         * as alternative to the default bean property access.
277         * @see #initBeanPropertyAccess()
278         * @see #createDirectFieldBindingResult()
279         */
280        public void initDirectFieldAccess() {
281                Assert.state(this.bindingResult == null,
282                                "DataBinder is already initialized - call initDirectFieldAccess before other configuration methods");
283                this.bindingResult = createDirectFieldBindingResult();
284        }
285
286        /**
287         * Create the {@link AbstractPropertyBindingResult} instance using direct
288         * field access.
289         * @since 4.2.1
290         */
291        protected AbstractPropertyBindingResult createDirectFieldBindingResult() {
292                DirectFieldBindingResult result = new DirectFieldBindingResult(getTarget(),
293                                getObjectName(), isAutoGrowNestedPaths());
294
295                if (this.conversionService != null) {
296                        result.initConversion(this.conversionService);
297                }
298                if (this.messageCodesResolver != null) {
299                        result.setMessageCodesResolver(this.messageCodesResolver);
300                }
301
302                return result;
303        }
304
305        /**
306         * Return the internal BindingResult held by this DataBinder,
307         * as an AbstractPropertyBindingResult.
308         */
309        protected AbstractPropertyBindingResult getInternalBindingResult() {
310                if (this.bindingResult == null) {
311                        initBeanPropertyAccess();
312                }
313                return this.bindingResult;
314        }
315
316        /**
317         * Return the underlying PropertyAccessor of this binder's BindingResult.
318         */
319        protected ConfigurablePropertyAccessor getPropertyAccessor() {
320                return getInternalBindingResult().getPropertyAccessor();
321        }
322
323        /**
324         * Return this binder's underlying SimpleTypeConverter.
325         */
326        protected SimpleTypeConverter getSimpleTypeConverter() {
327                if (this.typeConverter == null) {
328                        this.typeConverter = new SimpleTypeConverter();
329                        if (this.conversionService != null) {
330                                this.typeConverter.setConversionService(this.conversionService);
331                        }
332                }
333                return this.typeConverter;
334        }
335
336        /**
337         * Return the underlying TypeConverter of this binder's BindingResult.
338         */
339        protected PropertyEditorRegistry getPropertyEditorRegistry() {
340                if (getTarget() != null) {
341                        return getInternalBindingResult().getPropertyAccessor();
342                }
343                else {
344                        return getSimpleTypeConverter();
345                }
346        }
347
348        /**
349         * Return the underlying TypeConverter of this binder's BindingResult.
350         */
351        protected TypeConverter getTypeConverter() {
352                if (getTarget() != null) {
353                        return getInternalBindingResult().getPropertyAccessor();
354                }
355                else {
356                        return getSimpleTypeConverter();
357                }
358        }
359
360        /**
361         * Return the BindingResult instance created by this DataBinder.
362         * This allows for convenient access to the binding results after
363         * a bind operation.
364         * @return the BindingResult instance, to be treated as BindingResult
365         * or as Errors instance (Errors is a super-interface of BindingResult)
366         * @see Errors
367         * @see #bind
368         */
369        public BindingResult getBindingResult() {
370                return getInternalBindingResult();
371        }
372
373
374        /**
375         * Set whether to ignore unknown fields, that is, whether to ignore bind
376         * parameters that do not have corresponding fields in the target object.
377         * <p>Default is "true". Turn this off to enforce that all bind parameters
378         * must have a matching field in the target object.
379         * <p>Note that this setting only applies to <i>binding</i> operations
380         * on this DataBinder, not to <i>retrieving</i> values via its
381         * {@link #getBindingResult() BindingResult}.
382         * @see #bind
383         */
384        public void setIgnoreUnknownFields(boolean ignoreUnknownFields) {
385                this.ignoreUnknownFields = ignoreUnknownFields;
386        }
387
388        /**
389         * Return whether to ignore unknown fields when binding.
390         */
391        public boolean isIgnoreUnknownFields() {
392                return this.ignoreUnknownFields;
393        }
394
395        /**
396         * Set whether to ignore invalid fields, that is, whether to ignore bind
397         * parameters that have corresponding fields in the target object which are
398         * not accessible (for example because of null values in the nested path).
399         * <p>Default is "false". Turn this on to ignore bind parameters for
400         * nested objects in non-existing parts of the target object graph.
401         * <p>Note that this setting only applies to <i>binding</i> operations
402         * on this DataBinder, not to <i>retrieving</i> values via its
403         * {@link #getBindingResult() BindingResult}.
404         * @see #bind
405         */
406        public void setIgnoreInvalidFields(boolean ignoreInvalidFields) {
407                this.ignoreInvalidFields = ignoreInvalidFields;
408        }
409
410        /**
411         * Return whether to ignore invalid fields when binding.
412         */
413        public boolean isIgnoreInvalidFields() {
414                return this.ignoreInvalidFields;
415        }
416
417        /**
418         * Register fields that should be allowed for binding. Default is all
419         * fields. Restrict this for example to avoid unwanted modifications
420         * by malicious users when binding HTTP request parameters.
421         * <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
422         * can be implemented by overriding the {@code isAllowed} method.
423         * <p>Alternatively, specify a list of <i>disallowed</i> fields.
424         * @param allowedFields array of field names
425         * @see #setDisallowedFields
426         * @see #isAllowed(String)
427         */
428        public void setAllowedFields(@Nullable String... allowedFields) {
429                this.allowedFields = PropertyAccessorUtils.canonicalPropertyNames(allowedFields);
430        }
431
432        /**
433         * Return the fields that should be allowed for binding.
434         * @return array of field names
435         */
436        @Nullable
437        public String[] getAllowedFields() {
438                return this.allowedFields;
439        }
440
441        /**
442         * Register fields that should <i>not</i> be allowed for binding. Default is none.
443         * Mark fields as disallowed for example to avoid unwanted modifications
444         * by malicious users when binding HTTP request parameters.
445         * <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
446         * can be implemented by overriding the {@code isAllowed} method.
447         * <p>Alternatively, specify a list of <i>allowed</i> fields.
448         * @param disallowedFields array of field names
449         * @see #setAllowedFields
450         * @see #isAllowed(String)
451         */
452        public void setDisallowedFields(@Nullable String... disallowedFields) {
453                this.disallowedFields = PropertyAccessorUtils.canonicalPropertyNames(disallowedFields);
454        }
455
456        /**
457         * Return the fields that should <i>not</i> be allowed for binding.
458         * @return array of field names
459         */
460        @Nullable
461        public String[] getDisallowedFields() {
462                return this.disallowedFields;
463        }
464
465        /**
466         * Register fields that are required for each binding process.
467         * <p>If one of the specified fields is not contained in the list of
468         * incoming property values, a corresponding "missing field" error
469         * will be created, with error code "required" (by the default
470         * binding error processor).
471         * @param requiredFields array of field names
472         * @see #setBindingErrorProcessor
473         * @see DefaultBindingErrorProcessor#MISSING_FIELD_ERROR_CODE
474         */
475        public void setRequiredFields(@Nullable String... requiredFields) {
476                this.requiredFields = PropertyAccessorUtils.canonicalPropertyNames(requiredFields);
477                if (logger.isDebugEnabled()) {
478                        logger.debug("DataBinder requires binding of required fields [" +
479                                        StringUtils.arrayToCommaDelimitedString(requiredFields) + "]");
480                }
481        }
482
483        /**
484         * Return the fields that are required for each binding process.
485         * @return array of field names
486         */
487        @Nullable
488        public String[] getRequiredFields() {
489                return this.requiredFields;
490        }
491
492        /**
493         * Set the strategy to use for resolving errors into message codes.
494         * Applies the given strategy to the underlying errors holder.
495         * <p>Default is a DefaultMessageCodesResolver.
496         * @see BeanPropertyBindingResult#setMessageCodesResolver
497         * @see DefaultMessageCodesResolver
498         */
499        public void setMessageCodesResolver(@Nullable MessageCodesResolver messageCodesResolver) {
500                Assert.state(this.messageCodesResolver == null, "DataBinder is already initialized with MessageCodesResolver");
501                this.messageCodesResolver = messageCodesResolver;
502                if (this.bindingResult != null && messageCodesResolver != null) {
503                        this.bindingResult.setMessageCodesResolver(messageCodesResolver);
504                }
505        }
506
507        /**
508         * Set the strategy to use for processing binding errors, that is,
509         * required field errors and {@code PropertyAccessException}s.
510         * <p>Default is a DefaultBindingErrorProcessor.
511         * @see DefaultBindingErrorProcessor
512         */
513        public void setBindingErrorProcessor(BindingErrorProcessor bindingErrorProcessor) {
514                Assert.notNull(bindingErrorProcessor, "BindingErrorProcessor must not be null");
515                this.bindingErrorProcessor = bindingErrorProcessor;
516        }
517
518        /**
519         * Return the strategy for processing binding errors.
520         */
521        public BindingErrorProcessor getBindingErrorProcessor() {
522                return this.bindingErrorProcessor;
523        }
524
525        /**
526         * Set the Validator to apply after each binding step.
527         * @see #addValidators(Validator...)
528         * @see #replaceValidators(Validator...)
529         */
530        public void setValidator(@Nullable Validator validator) {
531                assertValidators(validator);
532                this.validators.clear();
533                if (validator != null) {
534                        this.validators.add(validator);
535                }
536        }
537
538        private void assertValidators(Validator... validators) {
539                Object target = getTarget();
540                for (Validator validator : validators) {
541                        if (validator != null && (target != null && !validator.supports(target.getClass()))) {
542                                throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + target);
543                        }
544                }
545        }
546
547        /**
548         * Add Validators to apply after each binding step.
549         * @see #setValidator(Validator)
550         * @see #replaceValidators(Validator...)
551         */
552        public void addValidators(Validator... validators) {
553                assertValidators(validators);
554                this.validators.addAll(Arrays.asList(validators));
555        }
556
557        /**
558         * Replace the Validators to apply after each binding step.
559         * @see #setValidator(Validator)
560         * @see #addValidators(Validator...)
561         */
562        public void replaceValidators(Validator... validators) {
563                assertValidators(validators);
564                this.validators.clear();
565                this.validators.addAll(Arrays.asList(validators));
566        }
567
568        /**
569         * Return the primary Validator to apply after each binding step, if any.
570         */
571        @Nullable
572        public Validator getValidator() {
573                return (!this.validators.isEmpty() ? this.validators.get(0) : null);
574        }
575
576        /**
577         * Return the Validators to apply after data binding.
578         */
579        public List<Validator> getValidators() {
580                return Collections.unmodifiableList(this.validators);
581        }
582
583
584        //---------------------------------------------------------------------
585        // Implementation of PropertyEditorRegistry/TypeConverter interface
586        //---------------------------------------------------------------------
587
588        /**
589         * Specify a Spring 3.0 ConversionService to use for converting
590         * property values, as an alternative to JavaBeans PropertyEditors.
591         */
592        public void setConversionService(@Nullable ConversionService conversionService) {
593                Assert.state(this.conversionService == null, "DataBinder is already initialized with ConversionService");
594                this.conversionService = conversionService;
595                if (this.bindingResult != null && conversionService != null) {
596                        this.bindingResult.initConversion(conversionService);
597                }
598        }
599
600        /**
601         * Return the associated ConversionService, if any.
602         */
603        @Nullable
604        public ConversionService getConversionService() {
605                return this.conversionService;
606        }
607
608        /**
609         * Add a custom formatter, applying it to all fields matching the
610         * {@link Formatter}-declared type.
611         * <p>Registers a corresponding {@link PropertyEditor} adapter underneath the covers.
612         * @param formatter the formatter to add, generically declared for a specific type
613         * @since 4.2
614         * @see #registerCustomEditor(Class, PropertyEditor)
615         */
616        public void addCustomFormatter(Formatter<?> formatter) {
617                FormatterPropertyEditorAdapter adapter = new FormatterPropertyEditorAdapter(formatter);
618                getPropertyEditorRegistry().registerCustomEditor(adapter.getFieldType(), adapter);
619        }
620
621        /**
622         * Add a custom formatter for the field type specified in {@link Formatter} class,
623         * applying it to the specified fields only, if any, or otherwise to all fields.
624         * <p>Registers a corresponding {@link PropertyEditor} adapter underneath the covers.
625         * @param formatter the formatter to add, generically declared for a specific type
626         * @param fields the fields to apply the formatter to, or none if to be applied to all
627         * @since 4.2
628         * @see #registerCustomEditor(Class, String, PropertyEditor)
629         */
630        public void addCustomFormatter(Formatter<?> formatter, String... fields) {
631                FormatterPropertyEditorAdapter adapter = new FormatterPropertyEditorAdapter(formatter);
632                Class<?> fieldType = adapter.getFieldType();
633                if (ObjectUtils.isEmpty(fields)) {
634                        getPropertyEditorRegistry().registerCustomEditor(fieldType, adapter);
635                }
636                else {
637                        for (String field : fields) {
638                                getPropertyEditorRegistry().registerCustomEditor(fieldType, field, adapter);
639                        }
640                }
641        }
642
643        /**
644         * Add a custom formatter, applying it to the specified field types only, if any,
645         * or otherwise to all fields matching the {@link Formatter}-declared type.
646         * <p>Registers a corresponding {@link PropertyEditor} adapter underneath the covers.
647         * @param formatter the formatter to add (does not need to generically declare a
648         * field type if field types are explicitly specified as parameters)
649         * @param fieldTypes the field types to apply the formatter to, or none if to be
650         * derived from the given {@link Formatter} implementation class
651         * @since 4.2
652         * @see #registerCustomEditor(Class, PropertyEditor)
653         */
654        public void addCustomFormatter(Formatter<?> formatter, Class<?>... fieldTypes) {
655                FormatterPropertyEditorAdapter adapter = new FormatterPropertyEditorAdapter(formatter);
656                if (ObjectUtils.isEmpty(fieldTypes)) {
657                        getPropertyEditorRegistry().registerCustomEditor(adapter.getFieldType(), adapter);
658                }
659                else {
660                        for (Class<?> fieldType : fieldTypes) {
661                                getPropertyEditorRegistry().registerCustomEditor(fieldType, adapter);
662                        }
663                }
664        }
665
666        @Override
667        public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
668                getPropertyEditorRegistry().registerCustomEditor(requiredType, propertyEditor);
669        }
670
671        @Override
672        public void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String field, PropertyEditor propertyEditor) {
673                getPropertyEditorRegistry().registerCustomEditor(requiredType, field, propertyEditor);
674        }
675
676        @Override
677        @Nullable
678        public PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath) {
679                return getPropertyEditorRegistry().findCustomEditor(requiredType, propertyPath);
680        }
681
682        @Override
683        @Nullable
684        public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException {
685                return getTypeConverter().convertIfNecessary(value, requiredType);
686        }
687
688        @Override
689        @Nullable
690        public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
691                        @Nullable MethodParameter methodParam) throws TypeMismatchException {
692
693                return getTypeConverter().convertIfNecessary(value, requiredType, methodParam);
694        }
695
696        @Override
697        @Nullable
698        public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
699                        throws TypeMismatchException {
700
701                return getTypeConverter().convertIfNecessary(value, requiredType, field);
702        }
703
704        @Nullable
705        @Override
706        public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
707                        @Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
708
709                return getTypeConverter().convertIfNecessary(value, requiredType, typeDescriptor);
710        }
711
712
713        /**
714         * Bind the given property values to this binder's target.
715         * <p>This call can create field errors, representing basic binding
716         * errors like a required field (code "required"), or type mismatch
717         * between value and bean property (code "typeMismatch").
718         * <p>Note that the given PropertyValues should be a throwaway instance:
719         * For efficiency, it will be modified to just contain allowed fields if it
720         * implements the MutablePropertyValues interface; else, an internal mutable
721         * copy will be created for this purpose. Pass in a copy of the PropertyValues
722         * if you want your original instance to stay unmodified in any case.
723         * @param pvs property values to bind
724         * @see #doBind(org.springframework.beans.MutablePropertyValues)
725         */
726        public void bind(PropertyValues pvs) {
727                MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues ?
728                                (MutablePropertyValues) pvs : new MutablePropertyValues(pvs));
729                doBind(mpvs);
730        }
731
732        /**
733         * Actual implementation of the binding process, working with the
734         * passed-in MutablePropertyValues instance.
735         * @param mpvs the property values to bind,
736         * as MutablePropertyValues instance
737         * @see #checkAllowedFields
738         * @see #checkRequiredFields
739         * @see #applyPropertyValues
740         */
741        protected void doBind(MutablePropertyValues mpvs) {
742                checkAllowedFields(mpvs);
743                checkRequiredFields(mpvs);
744                applyPropertyValues(mpvs);
745        }
746
747        /**
748         * Check the given property values against the allowed fields,
749         * removing values for fields that are not allowed.
750         * @param mpvs the property values to be bound (can be modified)
751         * @see #getAllowedFields
752         * @see #isAllowed(String)
753         */
754        protected void checkAllowedFields(MutablePropertyValues mpvs) {
755                PropertyValue[] pvs = mpvs.getPropertyValues();
756                for (PropertyValue pv : pvs) {
757                        String field = PropertyAccessorUtils.canonicalPropertyName(pv.getName());
758                        if (!isAllowed(field)) {
759                                mpvs.removePropertyValue(pv);
760                                getBindingResult().recordSuppressedField(field);
761                                if (logger.isDebugEnabled()) {
762                                        logger.debug("Field [" + field + "] has been removed from PropertyValues " +
763                                                        "and will not be bound, because it has not been found in the list of allowed fields");
764                                }
765                        }
766                }
767        }
768
769        /**
770         * Return if the given field is allowed for binding.
771         * Invoked for each passed-in property value.
772         * <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
773         * as well as direct equality, in the specified lists of allowed fields and
774         * disallowed fields. A field matching a disallowed pattern will not be accepted
775         * even if it also happens to match a pattern in the allowed list.
776         * <p>Can be overridden in subclasses.
777         * @param field the field to check
778         * @return if the field is allowed
779         * @see #setAllowedFields
780         * @see #setDisallowedFields
781         * @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
782         */
783        protected boolean isAllowed(String field) {
784                String[] allowed = getAllowedFields();
785                String[] disallowed = getDisallowedFields();
786                return ((ObjectUtils.isEmpty(allowed) || PatternMatchUtils.simpleMatch(allowed, field)) &&
787                                (ObjectUtils.isEmpty(disallowed) || !PatternMatchUtils.simpleMatch(disallowed, field)));
788        }
789
790        /**
791         * Check the given property values against the required fields,
792         * generating missing field errors where appropriate.
793         * @param mpvs the property values to be bound (can be modified)
794         * @see #getRequiredFields
795         * @see #getBindingErrorProcessor
796         * @see BindingErrorProcessor#processMissingFieldError
797         */
798        protected void checkRequiredFields(MutablePropertyValues mpvs) {
799                String[] requiredFields = getRequiredFields();
800                if (!ObjectUtils.isEmpty(requiredFields)) {
801                        Map<String, PropertyValue> propertyValues = new HashMap<>();
802                        PropertyValue[] pvs = mpvs.getPropertyValues();
803                        for (PropertyValue pv : pvs) {
804                                String canonicalName = PropertyAccessorUtils.canonicalPropertyName(pv.getName());
805                                propertyValues.put(canonicalName, pv);
806                        }
807                        for (String field : requiredFields) {
808                                PropertyValue pv = propertyValues.get(field);
809                                boolean empty = (pv == null || pv.getValue() == null);
810                                if (!empty) {
811                                        if (pv.getValue() instanceof String) {
812                                                empty = !StringUtils.hasText((String) pv.getValue());
813                                        }
814                                        else if (pv.getValue() instanceof String[]) {
815                                                String[] values = (String[]) pv.getValue();
816                                                empty = (values.length == 0 || !StringUtils.hasText(values[0]));
817                                        }
818                                }
819                                if (empty) {
820                                        // Use bind error processor to create FieldError.
821                                        getBindingErrorProcessor().processMissingFieldError(field, getInternalBindingResult());
822                                        // Remove property from property values to bind:
823                                        // It has already caused a field error with a rejected value.
824                                        if (pv != null) {
825                                                mpvs.removePropertyValue(pv);
826                                                propertyValues.remove(field);
827                                        }
828                                }
829                        }
830                }
831        }
832
833        /**
834         * Apply given property values to the target object.
835         * <p>Default implementation applies all of the supplied property
836         * values as bean property values. By default, unknown fields will
837         * be ignored.
838         * @param mpvs the property values to be bound (can be modified)
839         * @see #getTarget
840         * @see #getPropertyAccessor
841         * @see #isIgnoreUnknownFields
842         * @see #getBindingErrorProcessor
843         * @see BindingErrorProcessor#processPropertyAccessException
844         */
845        protected void applyPropertyValues(MutablePropertyValues mpvs) {
846                try {
847                        // Bind request parameters onto target object.
848                        getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
849                }
850                catch (PropertyBatchUpdateException ex) {
851                        // Use bind error processor to create FieldErrors.
852                        for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
853                                getBindingErrorProcessor().processPropertyAccessException(pae, getInternalBindingResult());
854                        }
855                }
856        }
857
858
859        /**
860         * Invoke the specified Validators, if any.
861         * @see #setValidator(Validator)
862         * @see #getBindingResult()
863         */
864        public void validate() {
865                Object target = getTarget();
866                Assert.state(target != null, "No target to validate");
867                BindingResult bindingResult = getBindingResult();
868                // Call each validator with the same binding result
869                for (Validator validator : getValidators()) {
870                        validator.validate(target, bindingResult);
871                }
872        }
873
874        /**
875         * Invoke the specified Validators, if any, with the given validation hints.
876         * <p>Note: Validation hints may get ignored by the actual target Validator.
877         * @param validationHints one or more hint objects to be passed to a {@link SmartValidator}
878         * @since 3.1
879         * @see #setValidator(Validator)
880         * @see SmartValidator#validate(Object, Errors, Object...)
881         */
882        public void validate(Object... validationHints) {
883                Object target = getTarget();
884                Assert.state(target != null, "No target to validate");
885                BindingResult bindingResult = getBindingResult();
886                // Call each validator with the same binding result
887                for (Validator validator : getValidators()) {
888                        if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) {
889                                ((SmartValidator) validator).validate(target, bindingResult, validationHints);
890                        }
891                        else if (validator != null) {
892                                validator.validate(target, bindingResult);
893                        }
894                }
895        }
896
897        /**
898         * Close this DataBinder, which may result in throwing
899         * a BindException if it encountered any errors.
900         * @return the model Map, containing target object and Errors instance
901         * @throws BindException if there were any errors in the bind operation
902         * @see BindingResult#getModel()
903         */
904        public Map<?, ?> close() throws BindException {
905                if (getBindingResult().hasErrors()) {
906                        throw new BindException(getBindingResult());
907                }
908                return getBindingResult().getModel();
909        }
910
911}