001: /*
002: * Copyright 2002-2007 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: * http://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:
017: package org.springframework.beans.factory.config;
018:
019: import java.beans.PropertyEditor;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import org.springframework.beans.BeansException;
024: import org.springframework.beans.PropertyEditorRegistrar;
025: import org.springframework.beans.factory.BeanClassLoaderAware;
026: import org.springframework.core.Ordered;
027: import org.springframework.util.ClassUtils;
028:
029: /**
030: * {@link BeanFactoryPostProcessor} implementation that allows for convenient
031: * registration of custom {@link PropertyEditor property editors}.
032: *
033: * <p>As of Spring 2.0, the recommended usage is to use custom
034: * {@link PropertyEditorRegistrar} implementations that in turn register
035: * any desired editors on a given
036: * {@link org.springframework.beans.PropertyEditorRegistry registry}.
037: * Each PropertyEditorRegistrar can register any number of custom editors.
038: *
039: * <pre class="code">
040: * <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
041: * <property name="propertyEditorRegistrars">
042: * <list>
043: * <bean class="mypackage.MyCustomDateEditorRegistrar"/>
044: * <bean class="mypackage.MyObjectEditorRegistrar"/>
045: * </list>
046: * </property>
047: * </bean></pre>
048: *
049: * <p>Alternative configuration example with custom editor instances,
050: * assuming inner beans for <code>PropertyEditor</code> instances:
051: *
052: * <pre class="code">
053: * <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
054: * <property name="customEditors">
055: * <map>
056: * <entry key="java.util.Date">
057: * <bean class="mypackage.MyCustomDateEditor"/>
058: * </entry>
059: * <entry key="mypackage.MyObject">
060: * <bean id="myEditor" class="mypackage.MyObjectEditor">
061: * <property name="myParam"><value>myValue</value></property>
062: * </bean>
063: * </entry>
064: * </map>
065: * </property>
066: * </bean></pre>
067: *
068: * <p>Also supports "java.lang.String[]"-style array class names and primitive
069: * class names (e.g. "boolean"). Delegates to {@link ClassUtils} for actual
070: * class name resolution.
071: *
072: * <p><b>NOTE:</b> Custom property editors registered with this configurer do
073: * <i>not</i> apply to data binding. Custom editors for data binding need to
074: * be registered on the {@link org.springframework.validation.DataBinder}:
075: * Use a common base class or delegate to common PropertyEditorRegistrar
076: * implementations to reuse editor registration there.
077: *
078: * @author Juergen Hoeller
079: * @since 27.02.2004
080: * @see java.beans.PropertyEditor
081: * @see org.springframework.beans.PropertyEditorRegistrar
082: * @see ConfigurableBeanFactory#addPropertyEditorRegistrar
083: * @see ConfigurableBeanFactory#registerCustomEditor
084: * @see org.springframework.validation.DataBinder#registerCustomEditor
085: * @see org.springframework.web.servlet.mvc.BaseCommandController#setPropertyEditorRegistrars
086: * @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder
087: */
088: public class CustomEditorConfigurer implements
089: BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered {
090:
091: private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
092:
093: private PropertyEditorRegistrar[] propertyEditorRegistrars;
094:
095: private Map customEditors;
096:
097: private ClassLoader beanClassLoader = ClassUtils
098: .getDefaultClassLoader();
099:
100: public void setOrder(int order) {
101: this .order = order;
102: }
103:
104: public int getOrder() {
105: return this .order;
106: }
107:
108: /**
109: * Specify the {@link PropertyEditorRegistrar PropertyEditorRegistrars}
110: * to apply to beans defined within the current application context.
111: * <p>This allows for sharing <code>PropertyEditorRegistrars</code> with
112: * {@link org.springframework.validation.DataBinder DataBinders}, etc.
113: * Furthermore, it avoids the need for synchronization on custom editors:
114: * A <code>PropertyEditorRegistrar</code> will always create fresh editor
115: * instances for each bean creation attempt.
116: * @see ConfigurableListableBeanFactory#addPropertyEditorRegistrar
117: */
118: public void setPropertyEditorRegistrars(
119: PropertyEditorRegistrar[] propertyEditorRegistrars) {
120: this .propertyEditorRegistrars = propertyEditorRegistrars;
121: }
122:
123: /**
124: * Specify the custom editors to register via a {@link Map}, using the
125: * class name of the required type as the key and the {@link PropertyEditor}
126: * instance as the value.
127: * @param customEditors said <code>Map</code> of editors (can be <code>null</code>)
128: * @deprecated as of Spring 2.0.7, in favor of {@link #setPropertyEditorRegistrars}
129: * @see ConfigurableListableBeanFactory#registerCustomEditor
130: */
131: public void setCustomEditors(Map customEditors) {
132: this .customEditors = customEditors;
133: }
134:
135: public void setBeanClassLoader(ClassLoader beanClassLoader) {
136: this .beanClassLoader = beanClassLoader;
137: }
138:
139: public void postProcessBeanFactory(
140: ConfigurableListableBeanFactory beanFactory)
141: throws BeansException {
142: if (this .propertyEditorRegistrars != null) {
143: for (int i = 0; i < this .propertyEditorRegistrars.length; i++) {
144: beanFactory
145: .addPropertyEditorRegistrar(this .propertyEditorRegistrars[i]);
146: }
147: }
148:
149: if (this .customEditors != null) {
150: for (Iterator it = this .customEditors.entrySet().iterator(); it
151: .hasNext();) {
152: Map.Entry entry = (Map.Entry) it.next();
153: Object key = entry.getKey();
154: Class requiredType = null;
155: if (key instanceof Class) {
156: requiredType = (Class) key;
157: } else if (key instanceof String) {
158: String className = (String) key;
159: requiredType = ClassUtils.resolveClassName(
160: className, this .beanClassLoader);
161: } else {
162: throw new IllegalArgumentException(
163: "Invalid key ["
164: + key
165: + "] for custom editor: needs to be Class or String.");
166: }
167: Object value = entry.getValue();
168: if (!(value instanceof PropertyEditor)) {
169: throw new IllegalArgumentException("Mapped value ["
170: + value + "] for custom editor key [" + key
171: + "] is not of required type ["
172: + PropertyEditor.class.getName() + "]");
173: }
174: beanFactory.registerCustomEditor(requiredType,
175: (PropertyEditor) value);
176: }
177: }
178: }
179:
180: }
|