diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java b/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java index 52c422459e..6b16c23ae9 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java @@ -266,7 +266,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry { * shared editor that might be used concurrently. * @param requiredType the type of the property * @param propertyEditor the shared editor to register + * @deprecated as of Spring 3.0, in favor of PropertyEditorRegistrars or ConversionService usage */ + @Deprecated public void registerSharedEditor(Class requiredType, PropertyEditor propertyEditor) { registerCustomEditor(requiredType, null, propertyEditor); if (this.sharedEditors == null) { diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/CustomEditorConfigurer.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/CustomEditorConfigurer.java index 1b18a4540d..5791c02951 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/CustomEditorConfigurer.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/config/CustomEditorConfigurer.java @@ -25,6 +25,8 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.FatalBeanException; import org.springframework.beans.PropertyEditorRegistrar; +import org.springframework.beans.PropertyEditorRegistry; +import org.springframework.beans.PropertyEditorRegistrySupport; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.core.Ordered; import org.springframework.util.Assert; @@ -90,7 +92,7 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla private PropertyEditorRegistrar[] propertyEditorRegistrars; - private Map customEditors; + private Map customEditors; private boolean ignoreUnresolvableEditors = false; @@ -123,10 +125,11 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla * Specify the custom editors to register via a {@link Map}, using the * class name of the required type as the key and the class name of the * associated {@link PropertyEditor} as value. - * @param customEditors said Map of editors (can be null) + *

Also supports {@link PropertyEditor} instances as values; however, + * this is deprecated since Spring 2.0.7! * @see ConfigurableListableBeanFactory#registerCustomEditor */ - public void setCustomEditors(Map customEditors) { + public void setCustomEditors(Map customEditors) { this.customEditors = customEditors; } @@ -156,16 +159,35 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla } if (this.customEditors != null) { - for (Map.Entry entry : this.customEditors.entrySet()) { + for (Map.Entry entry : this.customEditors.entrySet()) { String key = entry.getKey(); - String value = entry.getValue(); + Object value = entry.getValue(); Class requiredType = null; try { requiredType = ClassUtils.forName(key, this.beanClassLoader); - Class editorClass = ClassUtils.forName(value, this.beanClassLoader); - Assert.isAssignable(PropertyEditor.class, editorClass); - beanFactory.registerCustomEditor(requiredType, (Class) editorClass); + if (value instanceof PropertyEditor) { + if (logger.isWarnEnabled()) { + logger.warn("Passing PropertyEditor instances into CustomEditorConfigurer is deprecated: " + + "use PropertyEditorRegistrars or PropertyEditor class names instead. " + + "Offending key [" + key + "; offending editor instance: " + value); + } + beanFactory.addPropertyEditorRegistrar( + new SharedPropertyEditorRegistrar(requiredType, (PropertyEditor) value)); + } + else if (value instanceof Class) { + beanFactory.registerCustomEditor(requiredType, (Class) value); + } + else if (value instanceof String) { + Class editorClass = ClassUtils.forName((String) value, this.beanClassLoader); + Assert.isAssignable(PropertyEditor.class, editorClass); + beanFactory.registerCustomEditor(requiredType, (Class) editorClass); + } + else { + throw new IllegalArgumentException("Mapped value [" + value + "] for custom editor key [" + + key + "] is not of required type [" + PropertyEditor.class.getName() + + "] or a corresponding Class or String value indicating a PropertyEditor implementation"); + } } catch (ClassNotFoundException ex) { if (this.ignoreUnresolvableEditors) { @@ -181,4 +203,29 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla } } + + /** + * PropertyEditorRegistrar that registers a (deprecated) shared editor. + */ + private static class SharedPropertyEditorRegistrar implements PropertyEditorRegistrar { + + private final Class requiredType; + + private final PropertyEditor sharedEditor; + + public SharedPropertyEditorRegistrar(Class requiredType, PropertyEditor sharedEditor) { + this.requiredType = requiredType; + this.sharedEditor = sharedEditor; + } + + public void registerCustomEditors(PropertyEditorRegistry registry) { + if (!(registry instanceof PropertyEditorRegistrySupport)) { + throw new IllegalArgumentException("Cannot registered shared editor " + + "on non-PropertyEditorRegistrySupport registry: " + registry); + } + ((PropertyEditorRegistrySupport) registry).registerSharedEditor(this.requiredType, this.sharedEditor); + } + } + + } diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java index 3bf25cfb7e..3f9b822770 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 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,8 +16,7 @@ package org.springframework.beans.factory.config; -import static org.junit.Assert.*; - +import java.beans.PropertyEditor; import java.beans.PropertyEditorSupport; import java.text.DateFormat; import java.text.ParseException; @@ -26,7 +25,10 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import static org.junit.Assert.*; import org.junit.Test; +import test.beans.TestBean; + import org.springframework.beans.FatalBeanException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyEditorRegistrar; @@ -35,8 +37,6 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.propertyeditors.CustomDateEditor; -import test.beans.TestBean; - /** * Unit tests for {@link CustomEditorConfigurer}. * @@ -72,6 +72,29 @@ public final class CustomEditorConfigurerTests { assertEquals(df.parse("2.12.1975"), tb2.getSomeMap().get("myKey")); } + @Test + public void testCustomEditorConfigurerWithEditorInstance() throws ParseException { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + CustomEditorConfigurer cec = new CustomEditorConfigurer(); + Map editors = new HashMap(); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN); + editors.put(Date.class.getName(), new CustomDateEditor(df, true)); + cec.setCustomEditors(editors); + cec.postProcessBeanFactory(bf); + + MutablePropertyValues pvs = new MutablePropertyValues(); + pvs.addPropertyValue("date", "2.12.1975"); + bf.registerBeanDefinition("tb1", new RootBeanDefinition(TestBean.class, pvs)); + pvs = new MutablePropertyValues(); + pvs.addPropertyValue("someMap[myKey]", new TypedStringValue("2.12.1975", Date.class)); + bf.registerBeanDefinition("tb2", new RootBeanDefinition(TestBean.class, pvs)); + + TestBean tb1 = (TestBean) bf.getBean("tb1"); + assertEquals(df.parse("2.12.1975"), tb1.getDate()); + TestBean tb2 = (TestBean) bf.getBean("tb2"); + assertEquals(df.parse("2.12.1975"), tb2.getSomeMap().get("myKey")); + } + @Test public void testCustomEditorConfigurerWithEditorClassName() throws ParseException { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); @@ -90,6 +113,24 @@ public final class CustomEditorConfigurerTests { assertEquals(df.parse("2.12.1975"), tb.getDate()); } + @Test + public void testCustomEditorConfigurerWithEditorAsClass() throws ParseException { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + CustomEditorConfigurer cec = new CustomEditorConfigurer(); + Map editors = new HashMap(); + editors.put(Date.class.getName(), MyDateEditor.class); + cec.setCustomEditors(editors); + cec.postProcessBeanFactory(bf); + + MutablePropertyValues pvs = new MutablePropertyValues(); + pvs.addPropertyValue("date", "2.12.1975"); + bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs)); + + TestBean tb = (TestBean) bf.getBean("tb"); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN); + assertEquals(df.parse("2.12.1975"), tb.getDate()); + } + @Test public void testCustomEditorConfigurerWithRequiredTypeArray() throws ParseException { DefaultListableBeanFactory bf = new DefaultListableBeanFactory();