revised core conversion package for BeanWrapper/BeanFactory integration
This commit is contained in:
@@ -21,6 +21,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the {@link PropertyAccessor} interface.
|
||||
* Provides base implementations of all convenience methods, with the
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -145,7 +146,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
* Create new BeanWrapperImpl, wrapping a new instance of the specified class.
|
||||
* @param clazz class to instantiate and wrap
|
||||
*/
|
||||
public BeanWrapperImpl(Class clazz) {
|
||||
public BeanWrapperImpl(Class<?> clazz) {
|
||||
registerDefaultEditors();
|
||||
setWrappedInstance(BeanUtils.instantiateClass(clazz));
|
||||
}
|
||||
@@ -365,8 +366,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object convertIfNecessary(
|
||||
Object value, Class requiredType, MethodParameter methodParam) throws TypeMismatchException {
|
||||
public <T> T convertIfNecessary(
|
||||
Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException {
|
||||
try {
|
||||
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
|
||||
}
|
||||
@@ -572,7 +573,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
Object value;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
try {
|
||||
@@ -580,8 +581,9 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
public Object run() throws Exception {
|
||||
return readMethod.invoke(object, (Object[]) null);
|
||||
}
|
||||
},acc);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
}, acc);
|
||||
}
|
||||
catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
}
|
||||
}
|
||||
@@ -625,7 +627,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
Map map = (Map) value;
|
||||
Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
|
||||
Class<?> mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), i + 1);
|
||||
// IMPORTANT: Do not pass full property name in here - property editors
|
||||
// must not kick in for map keys but rather only for map values.
|
||||
Object convertedMapKey = this.typeConverterDelegate.convertIfNecessary(key, mapKeyType);
|
||||
@@ -945,6 +947,11 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
|
||||
}
|
||||
}
|
||||
catch (ConversionException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
PropertyChangeEvent pce =
|
||||
new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
* Interface that encapsulates configuration methods for a PropertyAccessor.
|
||||
* Also extends the PropertyEditorRegistry interface, which defines methods
|
||||
@@ -29,6 +31,17 @@ package org.springframework.beans;
|
||||
*/
|
||||
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
void setConversionService(ConversionService conversionService);
|
||||
|
||||
/**
|
||||
* Return the associated ConversionService, if any.
|
||||
*/
|
||||
ConversionService getConversionService();
|
||||
|
||||
/**
|
||||
* Set whether to extract the old property value when applying a
|
||||
* property editor to a new value for a property.
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.springframework.beans.propertyeditors.PropertiesEditor;
|
||||
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
|
||||
import org.springframework.beans.propertyeditors.URIEditor;
|
||||
import org.springframework.beans.propertyeditors.URLEditor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourceArrayPropertyEditor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -75,6 +76,8 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private boolean defaultEditorsActive = false;
|
||||
|
||||
private boolean configValueEditorsActive = false;
|
||||
@@ -90,6 +93,22 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
private Map<Class, PropertyEditor> customEditorCache;
|
||||
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated ConversionService, if any.
|
||||
*/
|
||||
public ConversionService getConversionService() {
|
||||
return this.conversionService;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Management of default editors
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -160,6 +162,18 @@ class TypeConverterDelegate {
|
||||
// Custom editor for this type?
|
||||
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
|
||||
|
||||
// No custom editor but custom ConversionService specified?
|
||||
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
|
||||
if (editor == null && conversionService != null && convertedValue != null &&
|
||||
conversionService.canConvert(convertedValue.getClass(), requiredType)) {
|
||||
if (methodParam != null) {
|
||||
return (T) conversionService.convert(convertedValue, new TypeDescriptor(methodParam));
|
||||
}
|
||||
else {
|
||||
return conversionService.convert(convertedValue, requiredType);
|
||||
}
|
||||
}
|
||||
|
||||
// Value not of required type?
|
||||
if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
|
||||
if (editor == null) {
|
||||
@@ -265,7 +279,7 @@ class TypeConverterDelegate {
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
protected Object doConvertValue(Object oldValue, Object newValue, Class requiredType, PropertyEditor editor) {
|
||||
protected Object doConvertValue(Object oldValue, Object newValue, Class<?> requiredType, PropertyEditor editor) {
|
||||
Object convertedValue = newValue;
|
||||
boolean sharedEditor = false;
|
||||
|
||||
@@ -307,6 +321,8 @@ class TypeConverterDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
Object returnValue = convertedValue;
|
||||
|
||||
if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
|
||||
// Convert String array to a comma-separated String.
|
||||
// Only applies if no PropertyEditor converted the String array before.
|
||||
@@ -335,7 +351,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
return convertedValue;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,10 +56,10 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
*/
|
||||
public TypeMismatchException(PropertyChangeEvent propertyChangeEvent, Class requiredType, Throwable cause) {
|
||||
super(propertyChangeEvent,
|
||||
"Failed to convert property value of type [" +
|
||||
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "]" +
|
||||
"Failed to convert property value of type '" +
|
||||
ClassUtils.getDescriptiveType(propertyChangeEvent.getNewValue()) + "'" +
|
||||
(requiredType != null ?
|
||||
" to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : "") +
|
||||
" to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") +
|
||||
(propertyChangeEvent.getPropertyName() != null ?
|
||||
" for property '" + propertyChangeEvent.getPropertyName() + "'" : ""),
|
||||
cause);
|
||||
@@ -83,8 +83,8 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
* @param cause the root cause (may be <code>null</code>)
|
||||
*/
|
||||
public TypeMismatchException(Object value, Class requiredType, Throwable cause) {
|
||||
super("Failed to convert value of type [" + ClassUtils.getDescriptiveType(value) + "]" +
|
||||
(requiredType != null ? " to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" : ""),
|
||||
super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" +
|
||||
(requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : ""),
|
||||
cause);
|
||||
this.value = value;
|
||||
this.requiredType = requiredType;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
@@ -134,6 +135,17 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
*/
|
||||
BeanExpressionResolver getBeanExpressionResolver();
|
||||
|
||||
/**
|
||||
* Specify a Spring 3.0 ConversionService to use for converting
|
||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||
*/
|
||||
void setConversionService(ConversionService conversionService);
|
||||
|
||||
/**
|
||||
* Return the associated ConversionService, if any.
|
||||
*/
|
||||
ConversionService getConversionService();
|
||||
|
||||
/**
|
||||
* Add a PropertyEditorRegistrar to be applied to all bean creation processes.
|
||||
* <p>Such a registrar creates new PropertyEditor instances and registers them
|
||||
|
||||
@@ -66,6 +66,7 @@ import org.springframework.beans.factory.config.InstantiationAwareBeanPostProces
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.core.DecoratingClassLoader;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -120,6 +121,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
/** Resolution strategy for expressions in bean definition values */
|
||||
private BeanExpressionResolver beanExpressionResolver;
|
||||
|
||||
/** Spring 3.0 ConversionService to use instead of PropertyEditors */
|
||||
private ConversionService conversionService;
|
||||
|
||||
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
|
||||
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
|
||||
new LinkedHashSet<PropertyEditorRegistrar>(4);
|
||||
@@ -620,6 +624,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return this.beanExpressionResolver;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
return this.conversionService;
|
||||
}
|
||||
|
||||
public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
|
||||
Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
|
||||
this.propertyEditorRegistrars.add(registrar);
|
||||
@@ -669,6 +681,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
else {
|
||||
// Build default TypeConverter, registering custom editors.
|
||||
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
|
||||
typeConverter.setConversionService(getConversionService());
|
||||
registerCustomEditors(typeConverter);
|
||||
return typeConverter;
|
||||
}
|
||||
@@ -937,6 +950,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @param bw the BeanWrapper to initialize
|
||||
*/
|
||||
protected void initBeanWrapper(BeanWrapper bw) {
|
||||
bw.setConversionService(getConversionService());
|
||||
registerCustomEditors(bw);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,13 +37,6 @@ import java.util.Properties;
|
||||
* @see java.util.Properties#load
|
||||
*/
|
||||
public class PropertiesEditor extends PropertyEditorSupport {
|
||||
|
||||
/**
|
||||
* Any of these characters, if they're first after whitespace or first
|
||||
* on a line, mean that the line is a comment and should be ignored.
|
||||
*/
|
||||
private final static String COMMENT_MARKERS = "#!";
|
||||
|
||||
|
||||
/**
|
||||
* Convert {@link String} into {@link Properties}, considering it as
|
||||
|
||||
Reference in New Issue
Block a user