1 16 17 package org.springframework.validation; 18 19 import java.beans.PropertyEditor ; 20 import java.util.HashMap ; 21 import java.util.Map ; 22 23 import org.apache.commons.logging.Log; 24 import org.apache.commons.logging.LogFactory; 25 26 import org.springframework.beans.ConfigurablePropertyAccessor; 27 import org.springframework.beans.MutablePropertyValues; 28 import org.springframework.beans.PropertyAccessException; 29 import org.springframework.beans.PropertyAccessorUtils; 30 import org.springframework.beans.PropertyBatchUpdateException; 31 import org.springframework.beans.PropertyEditorRegistry; 32 import org.springframework.beans.PropertyValue; 33 import org.springframework.beans.PropertyValues; 34 import org.springframework.util.Assert; 35 import org.springframework.util.ObjectUtils; 36 import org.springframework.util.PatternMatchUtils; 37 import org.springframework.util.StringUtils; 38 39 98 public class DataBinder implements PropertyEditorRegistry { 99 100 101 public static final String DEFAULT_OBJECT_NAME = "target"; 102 103 104 107 protected static final Log logger = LogFactory.getLog(DataBinder.class); 108 109 private final Object target; 110 111 private final String objectName; 112 113 private AbstractPropertyBindingResult bindingResult; 114 115 private BindException bindException; 116 117 private boolean ignoreUnknownFields = true; 118 119 private boolean ignoreInvalidFields = false; 120 121 private String [] allowedFields; 122 123 private String [] disallowedFields; 124 125 private String [] requiredFields; 126 127 private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor(); 128 129 130 135 public DataBinder(Object target) { 136 this(target, DEFAULT_OBJECT_NAME); 137 } 138 139 144 public DataBinder(Object target, String objectName) { 145 Assert.notNull(target, "Target must not be null"); 146 this.target = target; 147 this.objectName = objectName; 148 } 149 150 151 154 public Object getTarget() { 155 return this.target; 156 } 157 158 161 public String getObjectName() { 162 return this.objectName; 163 } 164 165 170 public void initBeanPropertyAccess() { 171 Assert.isNull(this.bindingResult, 172 "DataBinder is already initialized - call initBeanPropertyAccess before any other configuration methods"); 173 this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName()); 174 } 175 176 181 public void initDirectFieldAccess() { 182 Assert.isNull(this.bindingResult, 183 "DataBinder is already initialized - call initDirectFieldAccess before any other configuration methods"); 184 this.bindingResult = new DirectFieldBindingResult(getTarget(), getObjectName()); 185 } 186 187 191 protected AbstractPropertyBindingResult getInternalBindingResult() { 192 if (this.bindingResult == null) { 193 initBeanPropertyAccess(); 194 } 195 return this.bindingResult; 196 } 197 198 202 protected ConfigurablePropertyAccessor getPropertyAccessor() { 203 return getInternalBindingResult().getPropertyAccessor(); 204 } 205 206 215 public BindingResult getBindingResult() { 216 return getInternalBindingResult(); 217 } 218 219 227 public BindException getErrors() { 228 if (this.bindException == null) { 229 this.bindException = new BindException(getBindingResult()); 230 } 231 return this.bindException; 232 } 233 234 235 245 public void setIgnoreUnknownFields(boolean ignoreUnknownFields) { 246 this.ignoreUnknownFields = ignoreUnknownFields; 247 } 248 249 252 public boolean isIgnoreUnknownFields() { 253 return this.ignoreUnknownFields; 254 } 255 256 267 public void setIgnoreInvalidFields(boolean ignoreInvalidFields) { 268 this.ignoreInvalidFields = ignoreInvalidFields; 269 } 270 271 274 public boolean isIgnoreInvalidFields() { 275 return this.ignoreInvalidFields; 276 } 277 278 290 public void setAllowedFields(String [] allowedFields) { 291 this.allowedFields = PropertyAccessorUtils.canonicalPropertyNames(allowedFields); 292 } 293 294 298 public String [] getAllowedFields() { 299 return this.allowedFields; 300 } 301 302 314 public void setDisallowedFields(String [] disallowedFields) { 315 this.disallowedFields = PropertyAccessorUtils.canonicalPropertyNames(disallowedFields); 316 } 317 318 322 public String [] getDisallowedFields() { 323 return this.disallowedFields; 324 } 325 326 336 public void setRequiredFields(String [] requiredFields) { 337 this.requiredFields = PropertyAccessorUtils.canonicalPropertyNames(requiredFields); 338 if (logger.isDebugEnabled()) { 339 logger.debug("DataBinder requires binding of required fields [" + 340 StringUtils.arrayToCommaDelimitedString(requiredFields) + "]"); 341 } 342 } 343 344 348 public String [] getRequiredFields() { 349 return this.requiredFields; 350 } 351 352 358 public void setExtractOldValueForEditor(boolean extractOldValueForEditor) { 359 getPropertyAccessor().setExtractOldValueForEditor(extractOldValueForEditor); 360 } 361 362 public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) { 363 getPropertyAccessor().registerCustomEditor(requiredType, propertyEditor); 364 } 365 366 public void registerCustomEditor(Class requiredType, String field, PropertyEditor propertyEditor) { 367 getPropertyAccessor().registerCustomEditor(requiredType, field, propertyEditor); 368 } 369 370 public PropertyEditor findCustomEditor(Class requiredType, String propertyPath) { 371 return getPropertyAccessor().findCustomEditor(requiredType, propertyPath); 372 } 373 374 381 public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) { 382 getInternalBindingResult().setMessageCodesResolver(messageCodesResolver); 383 } 384 385 391 public void setBindingErrorProcessor(BindingErrorProcessor bindingErrorProcessor) { 392 this.bindingErrorProcessor = bindingErrorProcessor; 393 } 394 395 398 public BindingErrorProcessor getBindingErrorProcessor() { 399 return bindingErrorProcessor; 400 } 401 402 403 416 public void bind(PropertyValues pvs) { 417 MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues) ? 418 (MutablePropertyValues) pvs : new MutablePropertyValues(pvs); 419 doBind(mpvs); 420 } 421 422 431 protected void doBind(MutablePropertyValues mpvs) { 432 checkAllowedFields(mpvs); 433 checkRequiredFields(mpvs); 434 applyPropertyValues(mpvs); 435 } 436 437 444 protected void checkAllowedFields(MutablePropertyValues mpvs) { 445 PropertyValue[] pvs = mpvs.getPropertyValues(); 446 for (int i = 0; i < pvs.length; i++) { 447 PropertyValue pv = pvs[i]; 448 String field = PropertyAccessorUtils.canonicalPropertyName(pv.getName()); 449 if (!isAllowed(field)) { 450 mpvs.removePropertyValue(pv); 451 getBindingResult().recordSuppressedField(field); 452 if (logger.isDebugEnabled()) { 453 logger.debug("Field [" + field + "] has been removed from PropertyValues " + 454 "and will not be bound, because it has not been found in the list of allowed fields"); 455 } 456 } 457 } 458 } 459 460 474 protected boolean isAllowed(String field) { 475 String [] allowed = getAllowedFields(); 476 String [] disallowed = getDisallowedFields(); 477 return ((ObjectUtils.isEmpty(allowed) || PatternMatchUtils.simpleMatch(allowed, field)) && 478 (ObjectUtils.isEmpty(disallowed) || !PatternMatchUtils.simpleMatch(disallowed, field))); 479 } 480 481 489 protected void checkRequiredFields(MutablePropertyValues mpvs) { 490 String [] requiredFields = getRequiredFields(); 491 if (!ObjectUtils.isEmpty(requiredFields)) { 492 Map propertyValues = new HashMap (); 493 PropertyValue[] pvs = mpvs.getPropertyValues(); 494 for (int i = 0; i < pvs.length; i++) { 495 PropertyValue pv = pvs[i]; 496 String canonicalName = PropertyAccessorUtils.canonicalPropertyName(pv.getName()); 497 propertyValues.put(canonicalName, pv); 498 } 499 for (int i = 0; i < requiredFields.length; i++) { 500 String field = requiredFields[i]; 501 PropertyValue pv = (PropertyValue) propertyValues.get(field); 502 if (pv == null || pv.getValue() == null || 503 (pv.getValue() instanceof String && !StringUtils.hasText((String ) pv.getValue()))) { 504 getBindingErrorProcessor().processMissingFieldError(field, getInternalBindingResult()); 506 if (pv != null) { 509 mpvs.removePropertyValue(pv); 510 propertyValues.remove(field); 511 } 512 } 513 } 514 } 515 } 516 517 529 protected void applyPropertyValues(MutablePropertyValues mpvs) { 530 try { 531 getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields()); 533 } 534 catch (PropertyBatchUpdateException ex) { 535 PropertyAccessException[] exs = ex.getPropertyAccessExceptions(); 537 for (int i = 0; i < exs.length; i++) { 538 getBindingErrorProcessor().processPropertyAccessException(exs[i], getInternalBindingResult()); 539 } 540 } 541 } 542 543 544 551 public Map close() throws BindException { 552 if (getBindingResult().hasErrors()) { 553 throw new BindException(getBindingResult()); 554 } 555 return getBindingResult().getModel(); 556 } 557 558 } 559 | Popular Tags |