support for default "conversionService" bean in an ApplicationContext; revised formatting package, now integrated with DataBinder and AnnotationMethodHandlerAdapter; revised AccessControlContext access from BeanFactory
This commit is contained in:
@@ -44,6 +44,13 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
|
||||
*/
|
||||
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
|
||||
|
||||
/**
|
||||
* Name of the ConversionService bean in the factory.
|
||||
* If none is supplied, default conversion rules apply.
|
||||
* @see org.springframework.core.convert.ConversionService
|
||||
*/
|
||||
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
|
||||
|
||||
/**
|
||||
* Name of the LoadTimeWeaver bean in the factory. If such a bean is supplied,
|
||||
* the context will use a temporary ClassLoader for type matching, in order
|
||||
|
||||
@@ -63,6 +63,7 @@ import org.springframework.context.weaving.LoadTimeWeaverAwareProcessor;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@@ -367,6 +368,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
// Register bean processors that intercept bean creation.
|
||||
registerBeanPostProcessors(beanFactory);
|
||||
|
||||
// Initialize conversion service for this context.
|
||||
initConversionService();
|
||||
|
||||
// Initialize message source for this context.
|
||||
initMessageSource();
|
||||
|
||||
@@ -605,6 +609,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the BeanFactory's ConversionService.
|
||||
*/
|
||||
protected void initConversionService() {
|
||||
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
|
||||
beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the MessageSource.
|
||||
* Use parent's if none defined in this context.
|
||||
|
||||
@@ -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.
|
||||
@@ -22,9 +22,6 @@ import java.security.PrivilegedAction;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -43,6 +40,7 @@ import org.springframework.context.ResourceLoaderAware;
|
||||
* underlying bean factory. Applications do not use this directly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Costin Leau
|
||||
* @since 10.10.2003
|
||||
* @see org.springframework.context.ResourceLoaderAware
|
||||
* @see org.springframework.context.MessageSourceAware
|
||||
@@ -52,37 +50,33 @@ import org.springframework.context.ResourceLoaderAware;
|
||||
*/
|
||||
class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
private final ConfigurableApplicationContext applicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ApplicationContextAwareProcessor for the given context.
|
||||
*/
|
||||
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
|
||||
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
|
||||
AccessControlContext acc = null;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
if (applicationContext instanceof ConfigurableApplicationContext) {
|
||||
ConfigurableListableBeanFactory factory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
|
||||
if (factory instanceof AbstractBeanFactory) {
|
||||
acc = ((AbstractBeanFactory) factory).getSecurityContextProvider().getAccessControlContext();
|
||||
|
||||
if (System.getSecurityManager() != null &&
|
||||
(bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
|
||||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
|
||||
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
|
||||
}
|
||||
|
||||
if (acc != null) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
doProcess(bean);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// optimize - check the bean class before creating the inner class + native call
|
||||
if (bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware
|
||||
|| bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
doProcess(bean);
|
||||
return null;
|
||||
}
|
||||
}, acc);
|
||||
}
|
||||
}, acc);
|
||||
}
|
||||
else {
|
||||
doProcess(bean);
|
||||
@@ -109,4 +103,5 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
||||
public Object postProcessAfterInitialization(Object bean, String name) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -55,7 +55,7 @@ public abstract class UiApplicationContextUtils {
|
||||
*/
|
||||
public static ThemeSource initThemeSource(ApplicationContext context) {
|
||||
if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
|
||||
ThemeSource themeSource = (ThemeSource) context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
|
||||
ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
|
||||
// Make ThemeSource aware of parent ThemeSource.
|
||||
if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
|
||||
HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* A factory that creates {@link Formatter formatters} to format property values on properties annotated with a particular format {@link Annotation}.
|
||||
* For example, a <code>CurrencyAnnotationFormatterFactory</code> might create a <code>Formatter</code> that formats a <code>BigDecimal</code> value set on a property annotated with <code>@CurrencyFormat</code>.
|
||||
* A factory that creates {@link Formatter formatters} to format property values on properties
|
||||
* annotated with a particular format {@link Annotation}.
|
||||
*
|
||||
* <p>For example, a <code>CurrencyAnnotationFormatterFactory</code> might create a <code>Formatter</code>
|
||||
* that formats a <code>BigDecimal</code> value set on a property annotated with <code>@CurrencyFormat</code>.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @param <A> The type of Annotation this factory uses to create Formatter instances
|
||||
@@ -34,4 +39,5 @@ public interface AnnotationFormatterFactory<A extends Annotation, T> {
|
||||
* @return the Formatter to use to format values of properties annotated with the annotation.
|
||||
*/
|
||||
Formatter<T> getFormatter(A annotation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -23,6 +24,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* A type that can be formatted as a String for display in a user interface.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
@@ -30,9 +32,10 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Formatted {
|
||||
|
||||
|
||||
/**
|
||||
* The Formatter that handles the formatting.
|
||||
* The Formatter that handles the formatting for the annotated element.
|
||||
*/
|
||||
Class<?> value();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format;
|
||||
|
||||
import java.text.ParseException;
|
||||
@@ -20,6 +21,7 @@ import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Formats objects of type T for display.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @param <T> the type of object this formatter can format
|
||||
@@ -42,4 +44,5 @@ public interface Formatter<T> {
|
||||
* @throws ParseException when a parse exception occurs
|
||||
*/
|
||||
T parse(String formatted, Locale locale) throws ParseException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@@ -21,6 +22,7 @@ import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* A shared registry of Formatters.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
@@ -42,21 +44,19 @@ public interface FormatterRegistry {
|
||||
* On parse, the decorator first delegates to the formatter to parse a <T>, then coerses the parsed value to type.
|
||||
* @param type the object type
|
||||
* @param targetFormatter the target formatter
|
||||
* @param <T> the type of object the target formatter formats
|
||||
*/
|
||||
<T> void add(Class<?> type, Formatter<T> targetFormatter);
|
||||
void add(Class<?> type, Formatter<?> targetFormatter);
|
||||
|
||||
/**
|
||||
* Adds a AnnotationFormatterFactory that returns the Formatter for properties annotated with a specific annotation.
|
||||
* @param factory the annotation formatter factory
|
||||
*/
|
||||
<A extends Annotation, T> void add(AnnotationFormatterFactory<A, T> factory);
|
||||
void add(AnnotationFormatterFactory<?, ?> factory);
|
||||
|
||||
/**
|
||||
* Get the Formatter for the type descriptor.
|
||||
* @return the Formatter, or <code>null</code> if no suitable one is registered
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
Formatter getFormatter(TypeDescriptor type);
|
||||
Formatter<Object> getFormatter(TypeDescriptor type);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format.date;
|
||||
|
||||
import java.text.DateFormat;
|
||||
@@ -21,37 +22,60 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
|
||||
/**
|
||||
* A formatter for {@link java.util.Date} types.
|
||||
* Allows the configuration of an explicit date pattern and locale.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see SimpleDateFormat
|
||||
*/
|
||||
public final class DateFormatter implements Formatter<Date> {
|
||||
|
||||
private static Log logger = LogFactory.getLog(DateFormatter.class);
|
||||
|
||||
/**
|
||||
* The default date pattern.
|
||||
*/
|
||||
private static final String DEFAULT_PATTERN = "yyyy-MM-dd";
|
||||
|
||||
private String pattern;
|
||||
|
||||
private int style = DateFormat.DEFAULT;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the pattern to use to format date values.
|
||||
* If not specified, the default pattern 'yyyy-MM-dd' is used.
|
||||
* @param pattern the date formatting pattern
|
||||
* Create a new default DateFormatter.
|
||||
*/
|
||||
public DateFormatter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DateFormatter for the given date pattern.
|
||||
*/
|
||||
public DateFormatter(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the pattern to use to format date values.
|
||||
* <p>If not specified, DateFormat's default style will be used.
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the style to use to format date values.
|
||||
* <p>If not specified, DateFormat's default style will be used.
|
||||
* @see DateFormat#DEFAULT
|
||||
* @see DateFormat#SHORT
|
||||
* @see DateFormat#MEDIUM
|
||||
* @see DateFormat#LONG
|
||||
* @see DateFormat#FULL
|
||||
*/
|
||||
public void setStyle(int style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
|
||||
public String format(Date date, Locale locale) {
|
||||
if (date == null) {
|
||||
return "";
|
||||
@@ -66,23 +90,17 @@ public final class DateFormatter implements Formatter<Date> {
|
||||
return getDateFormat(locale).parse(formatted);
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private DateFormat getDateFormat(Locale locale) {
|
||||
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
format.setLenient(false);
|
||||
if (format instanceof SimpleDateFormat) {
|
||||
String pattern = determinePattern(this.pattern);
|
||||
((SimpleDateFormat) format).applyPattern(pattern);
|
||||
} else {
|
||||
logger.warn("Unable to apply format pattern '" + pattern
|
||||
+ "'; Returned DateFormat is not a SimpleDateFormat");
|
||||
protected DateFormat getDateFormat(Locale locale) {
|
||||
DateFormat dateFormat;
|
||||
if (this.pattern != null) {
|
||||
dateFormat = new SimpleDateFormat(this.pattern, locale);
|
||||
}
|
||||
return format;
|
||||
else {
|
||||
dateFormat = DateFormat.getDateInstance(this.style, locale);
|
||||
}
|
||||
dateFormat.setLenient(false);
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
private String determinePattern(String pattern) {
|
||||
return pattern != null ? pattern : DEFAULT_PATTERN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format.support;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
import org.springframework.ui.format.FormatterRegistry;
|
||||
import org.springframework.ui.format.support.GenericFormatterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapter that exposes a {@link ConversionService} reference for a given
|
||||
* {@link org.springframework.ui.format.FormatterRegistry}, retrieving the current
|
||||
* Locale from {@link org.springframework.context.i18n.LocaleContextHolder}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class FormattingConversionServiceAdapter implements ConversionService {
|
||||
|
||||
private final FormatterRegistry formatterRegistry;
|
||||
|
||||
private final ConversionService targetConversionService;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FormattingConversionServiceAdapter for the given FormatterRegistry.
|
||||
* @param formatterRegistry the FormatterRegistry to wrap
|
||||
*/
|
||||
public FormattingConversionServiceAdapter(FormatterRegistry formatterRegistry) {
|
||||
Assert.notNull(formatterRegistry, "FormatterRegistry must not be null");
|
||||
this.formatterRegistry = formatterRegistry;
|
||||
if (formatterRegistry instanceof GenericFormatterRegistry) {
|
||||
this.targetConversionService = ((GenericFormatterRegistry) formatterRegistry).getConversionService();
|
||||
}
|
||||
else {
|
||||
this.targetConversionService = new DefaultConversionService();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
return canConvert(sourceType, TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
public boolean canConvert(Class<?> sourceType, TypeDescriptor targetType) {
|
||||
return (this.formatterRegistry.getFormatter(targetType) != null ||
|
||||
this.targetConversionService.canConvert(sourceType, targetType));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convert(Object source, Class<T> targetType) {
|
||||
return (T) convert(source, TypeDescriptor.valueOf(targetType));
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor targetType) {
|
||||
if (source instanceof String) {
|
||||
Formatter formatter = this.formatterRegistry.getFormatter(targetType);
|
||||
if (formatter != null) {
|
||||
try {
|
||||
return formatter.parse((String) source, LocaleContextHolder.getLocale());
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new ConversionFailedException(source, String.class, targetType.getType(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.targetConversionService.convert(source, targetType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ui.format.support;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapter that exposes a {@link java.beans.PropertyEditor} for any given
|
||||
* {@link org.springframework.ui.format.Formatter}, retrieving the current
|
||||
* Locale from {@link org.springframework.context.i18n.LocaleContextHolder}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class FormattingPropertyEditorAdapter extends PropertyEditorSupport {
|
||||
|
||||
private final Formatter<Object> formatter;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FormattingPropertyEditorAdapter for the given Formatter.
|
||||
* @param formatter the Formatter to wrap
|
||||
*/
|
||||
public FormattingPropertyEditorAdapter(Formatter<Object> formatter) {
|
||||
Assert.notNull(formatter, "Formatter must not be null");
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
try {
|
||||
setValue(this.formatter.parse(text, LocaleContextHolder.getLocale()));
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException("Failed to parse formatted value", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
return this.formatter.format(getValue(), LocaleContextHolder.getLocale());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2009 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.
|
||||
@@ -13,62 +13,74 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ui.format;
|
||||
|
||||
package org.springframework.ui.format.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ui.format.FormatterRegistry;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||
import org.springframework.ui.format.Formatted;
|
||||
|
||||
/**
|
||||
* A generic implementation of {@link FormatterRegistry} suitable for use in most environments.
|
||||
* A generic implementation of {@link org.springframework.ui.format.FormatterRegistry} suitable for use in most environments.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see #setConversionService(ConversionService)
|
||||
* @see #add(Formatter)
|
||||
* @see #add(Class, Formatter)
|
||||
* @see #add(AnnotationFormatterFactory)
|
||||
* @see #add(org.springframework.ui.format.Formatter)
|
||||
* @see #add(Class, org.springframework.ui.format.Formatter)
|
||||
* @see #add(org.springframework.ui.format.AnnotationFormatterFactory)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
public class GenericFormatterRegistry implements FormatterRegistry, BeanFactoryAware, Cloneable {
|
||||
|
||||
private Map<Class, Formatter> typeFormatters = new ConcurrentHashMap<Class, Formatter>();
|
||||
private final Map<Class, Formatter> typeFormatters = new ConcurrentHashMap<Class, Formatter>();
|
||||
|
||||
private Map<Class, AnnotationFormatterFactory> annotationFormatters = new HashMap<Class, AnnotationFormatterFactory>();
|
||||
private final Map<Class, AnnotationFormatterFactory> annotationFormatters =
|
||||
new ConcurrentHashMap<Class, AnnotationFormatterFactory>();
|
||||
|
||||
private ConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
private boolean shared = true;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the type conversion service that will be used to coerse objects to the types required for formatting.
|
||||
* Defaults to a {@link DefaultConversionService}.
|
||||
* @param conversionService the conversion service
|
||||
* @see #add(Class, Formatter)
|
||||
* Registers the formatters in the set provided.
|
||||
* JavaBean-friendly alternative to calling {@link #add(Formatter)}.
|
||||
* @see #add(Formatter)
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
public void setFormatters(Set<Formatter<?>> formatters) {
|
||||
for (Formatter<?> formatter : formatters) {
|
||||
add(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers the formatters in the map provided by type.
|
||||
* JavaBean-friendly alternative to calling {@link #add(Class, Formatter)}.
|
||||
* @param formatters the formatters map
|
||||
* @see #add(Class, Formatter)
|
||||
*/
|
||||
public void setFormatters(Map<Class<?>, Formatter<?>> formatters) {
|
||||
public void setFormatterMap(Map<Class<?>, Formatter<?>> formatters) {
|
||||
for (Map.Entry<Class<?>, Formatter<?>> entry : formatters.entrySet()) {
|
||||
add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
@@ -85,36 +97,103 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the type conversion service that will be used to coerce objects to the
|
||||
* types required for formatting. Defaults to a {@link DefaultConversionService}.
|
||||
* @see #add(Class, Formatter)
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type conversion service which this FormatterRegistry delegates to.
|
||||
*/
|
||||
public ConversionService getConversionService() {
|
||||
return this.conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the context's default ConversionService if none specified locally.
|
||||
*/
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (this.conversionService == null &&
|
||||
beanFactory.containsBean(ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME)) {
|
||||
this.conversionService = beanFactory.getBean(
|
||||
ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME, ConversionService.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// cloning support
|
||||
|
||||
/**
|
||||
* Specify whether this FormatterRegistry is shared, in which case newly
|
||||
* registered Formatters will be visible to other callers as well.
|
||||
* <p>A new GenericFormatterRegistry is considered as shared by default,
|
||||
* whereas a cloned GenericFormatterRegistry will be non-shared by default.
|
||||
* @see #clone()
|
||||
*/
|
||||
public void setShared(boolean shared) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this FormatterRegistry is shared, in which case newly
|
||||
* registered Formatters will be visible to other callers as well.
|
||||
*/
|
||||
public boolean isShared() {
|
||||
return this.shared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an independent clone of this FormatterRegistry.
|
||||
* @see #setShared
|
||||
*/
|
||||
@Override
|
||||
public GenericFormatterRegistry clone() {
|
||||
GenericFormatterRegistry clone = new GenericFormatterRegistry();
|
||||
clone.typeFormatters.putAll(this.typeFormatters);
|
||||
clone.annotationFormatters.putAll(this.annotationFormatters);
|
||||
clone.conversionService = this.conversionService;
|
||||
clone.shared = false;
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
// implementing FormatterRegistry
|
||||
|
||||
public <T> void add(Formatter<T> formatter) {
|
||||
typeFormatters.put(getFormattedObjectType(formatter.getClass()), formatter);
|
||||
this.typeFormatters.put(getFormattedObjectType(formatter.getClass()), formatter);
|
||||
}
|
||||
|
||||
public <T> void add(Class<?> type, Formatter<T> formatter) {
|
||||
public void add(Class<?> type, Formatter<?> formatter) {
|
||||
Class<?> formattedObjectType = getFormattedObjectType(formatter.getClass());
|
||||
if (!conversionService.canConvert(formattedObjectType, type)) {
|
||||
if (!this.conversionService.canConvert(formattedObjectType, type)) {
|
||||
throw new IllegalArgumentException("Unable to register formatter " + formatter + " for type [" + type.getName() + "]; not able to convert from [" + formattedObjectType.getName() + "] to parse");
|
||||
}
|
||||
if (!conversionService.canConvert(type, formattedObjectType)) {
|
||||
if (!this.conversionService.canConvert(type, formattedObjectType)) {
|
||||
throw new IllegalArgumentException("Unable to register formatter " + formatter + " for type [" + type.getName() + "]; not able to convert to [" + formattedObjectType.getName() + "] to format");
|
||||
}
|
||||
typeFormatters.put(type, formatter);
|
||||
this.typeFormatters.put(type, formatter);
|
||||
}
|
||||
|
||||
public <A extends Annotation, T> void add(AnnotationFormatterFactory<A, T> factory) {
|
||||
annotationFormatters.put(getAnnotationType(factory.getClass()), factory);
|
||||
public void add(AnnotationFormatterFactory<?, ?> factory) {
|
||||
this.annotationFormatters.put(getAnnotationType(factory.getClass()), factory);
|
||||
}
|
||||
|
||||
public Formatter<?> getFormatter(TypeDescriptor type) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Formatter<Object> getFormatter(TypeDescriptor type) {
|
||||
Assert.notNull(type, "The TypeDescriptor is required");
|
||||
Formatter formatter = getAnnotationFormatter(type);
|
||||
Formatter<Object> formatter = getAnnotationFormatter(type);
|
||||
if (formatter == null) {
|
||||
formatter = getTypeFormatter(type.getType());
|
||||
}
|
||||
return formatter;
|
||||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
|
||||
private Class getFormattedObjectType(Class formatterClass) {
|
||||
@@ -175,7 +254,8 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
+ factoryClass.getName() + "]; does the factory parameterize the <A> generic type?");
|
||||
}
|
||||
|
||||
private Formatter<?> getAnnotationFormatter(TypeDescriptor type) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private Formatter getAnnotationFormatter(TypeDescriptor type) {
|
||||
Annotation[] annotations = type.getAnnotations();
|
||||
for (Annotation a : annotations) {
|
||||
AnnotationFormatterFactory factory = annotationFormatters.get(a.annotationType());
|
||||
@@ -186,17 +266,19 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Formatter<?> getTypeFormatter(Class<?> type) {
|
||||
private Formatter getTypeFormatter(Class<?> type) {
|
||||
Assert.notNull(type, "The Class of the object to format is required");
|
||||
Formatter formatter = findFormatter(type);
|
||||
if (formatter != null) {
|
||||
Class<?> formattedObjectType = getFormattedObjectType(formatter.getClass());
|
||||
if (type.isAssignableFrom(formattedObjectType)) {
|
||||
return formatter;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return new ConvertingFormatter(type, formattedObjectType, formatter);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return getDefaultFormatter(type);
|
||||
}
|
||||
}
|
||||
@@ -236,11 +318,13 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
throw new IllegalStateException(
|
||||
"Formatter referenced by @Formatted annotation does not have public constructor", e);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ConvertingFormatter implements Formatter {
|
||||
|
||||
private Class<?> type;
|
||||
@@ -255,6 +339,7 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
this.targetFormatter = targetFormatter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String format(Object object, Locale locale) {
|
||||
object = conversionService.convert(object, formattedObjectType);
|
||||
return targetFormatter.format(object, locale);
|
||||
@@ -268,4 +353,4 @@ public class GenericFormatterRegistry implements FormatterRegistry {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Support classes for the formatting package, providing
|
||||
* common implementations as well as adapters.
|
||||
*/
|
||||
package org.springframework.ui.format;
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -65,6 +66,7 @@ public abstract class AbstractBindingResult extends AbstractErrors implements Bi
|
||||
* @see DefaultMessageCodesResolver
|
||||
*/
|
||||
public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) {
|
||||
Assert.notNull(messageCodesResolver, "MessageCodesResolver must not be null");
|
||||
this.messageCodesResolver = messageCodesResolver;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -22,6 +22,13 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.ConfigurablePropertyAccessor;
|
||||
import org.springframework.beans.PropertyAccessorUtils;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
import org.springframework.ui.format.FormatterRegistry;
|
||||
import org.springframework.ui.format.support.FormattingConversionServiceAdapter;
|
||||
import org.springframework.ui.format.support.FormattingPropertyEditorAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link BindingResult} implementations that work with
|
||||
@@ -37,6 +44,9 @@ import org.springframework.beans.PropertyEditorRegistry;
|
||||
*/
|
||||
public abstract class AbstractPropertyBindingResult extends AbstractBindingResult {
|
||||
|
||||
private FormatterRegistry formatterRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AbstractPropertyBindingResult instance.
|
||||
* @param objectName the name of the target object
|
||||
@@ -47,6 +57,12 @@ public abstract class AbstractPropertyBindingResult extends AbstractBindingResul
|
||||
}
|
||||
|
||||
|
||||
public void initFormatterLookup(FormatterRegistry formatterRegistry) {
|
||||
Assert.notNull(formatterRegistry, "FormatterRegistry must not be null");
|
||||
this.formatterRegistry = formatterRegistry;
|
||||
getPropertyAccessor().setConversionService(new FormattingConversionServiceAdapter(formatterRegistry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying PropertyAccessor.
|
||||
* @see #getPropertyAccessor()
|
||||
@@ -89,7 +105,13 @@ public abstract class AbstractPropertyBindingResult extends AbstractBindingResul
|
||||
*/
|
||||
@Override
|
||||
protected Object formatFieldValue(String field, Object value) {
|
||||
PropertyEditor customEditor = getCustomEditor(field);
|
||||
String fixedField = fixedField(field);
|
||||
TypeDescriptor td = getPropertyAccessor().getPropertyTypeDescriptor(fixedField);
|
||||
Formatter<Object> formatter = (this.formatterRegistry != null ? this.formatterRegistry.getFormatter(td) : null);
|
||||
if (formatter != null) {
|
||||
return formatter.format(value, LocaleContextHolder.getLocale());
|
||||
}
|
||||
PropertyEditor customEditor = getCustomEditor(fixedField);
|
||||
if (customEditor != null) {
|
||||
customEditor.setValue(value);
|
||||
String textValue = customEditor.getAsText();
|
||||
@@ -104,11 +126,10 @@ public abstract class AbstractPropertyBindingResult extends AbstractBindingResul
|
||||
|
||||
/**
|
||||
* Retrieve the custom PropertyEditor for the given field, if any.
|
||||
* @param field the field name
|
||||
* @param fixedField the fully qualified field name
|
||||
* @return the custom PropertyEditor, or <code>null</code>
|
||||
*/
|
||||
protected PropertyEditor getCustomEditor(String field) {
|
||||
String fixedField = fixedField(field);
|
||||
protected PropertyEditor getCustomEditor(String fixedField) {
|
||||
Class targetType = getPropertyAccessor().getPropertyType(fixedField);
|
||||
PropertyEditor editor = getPropertyAccessor().findCustomEditor(targetType, fixedField);
|
||||
if (editor == null) {
|
||||
@@ -117,6 +138,22 @@ public abstract class AbstractPropertyBindingResult extends AbstractBindingResul
|
||||
return editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation exposes a PropertyEditor adapter for a Formatter,
|
||||
* if applicable.
|
||||
*/
|
||||
@Override
|
||||
public PropertyEditor findEditor(String field, Class valueType) {
|
||||
TypeDescriptor td = (valueType != null ? TypeDescriptor.valueOf(valueType) :
|
||||
getPropertyAccessor().getPropertyTypeDescriptor(fixedField(field)));
|
||||
final Formatter<Object> formatter =
|
||||
(this.formatterRegistry != null ? this.formatterRegistry.getFormatter(td) : null);
|
||||
if (formatter != null) {
|
||||
return new FormattingPropertyEditorAdapter(formatter);
|
||||
}
|
||||
return super.findEditor(field, valueType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide the PropertyAccessor to work with, according to the
|
||||
|
||||
@@ -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.
|
||||
@@ -88,10 +88,10 @@ public interface BindingResult extends Errors {
|
||||
|
||||
/**
|
||||
* Find a custom property editor for the given type and property.
|
||||
* @param valueType the type of the property (can be <code>null</code> if a property
|
||||
* is given but should be specified in any case for consistency checking)
|
||||
* @param field the path of the property (name or nested path), or
|
||||
* <code>null</code> if looking for an editor for all properties of the given type
|
||||
* @param valueType the type of the property (can be <code>null</code> if a property
|
||||
* is given but should be specified in any case for consistency checking)
|
||||
* @return the registered editor, or <code>null</code> if none
|
||||
*/
|
||||
PropertyEditor findEditor(String field, Class valueType);
|
||||
|
||||
@@ -35,6 +35,9 @@ import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.ui.format.FormatterRegistry;
|
||||
import org.springframework.ui.format.support.GenericFormatterRegistry;
|
||||
import org.springframework.ui.format.support.FormattingConversionServiceAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
@@ -132,6 +135,8 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
|
||||
private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
|
||||
|
||||
private FormatterRegistry formatterRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DataBinder instance, with default object name.
|
||||
@@ -178,6 +183,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
Assert.isNull(this.bindingResult,
|
||||
"DataBinder is already initialized - call initBeanPropertyAccess before any other configuration methods");
|
||||
this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName());
|
||||
if (this.formatterRegistry != null) {
|
||||
this.bindingResult.initFormatterLookup(this.formatterRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,6 +197,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
Assert.isNull(this.bindingResult,
|
||||
"DataBinder is already initialized - call initDirectFieldAccess before any other configuration methods");
|
||||
this.bindingResult = new DirectFieldBindingResult(getTarget(), getObjectName());
|
||||
if (this.formatterRegistry != null) {
|
||||
this.bindingResult.initFormatterLookup(this.formatterRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,6 +226,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
protected SimpleTypeConverter getSimpleTypeConverter() {
|
||||
if (this.typeConverter == null) {
|
||||
this.typeConverter = new SimpleTypeConverter();
|
||||
if (this.formatterRegistry != null) {
|
||||
this.typeConverter.setConversionService(new FormattingConversionServiceAdapter(this.formatterRegistry));
|
||||
}
|
||||
}
|
||||
return this.typeConverter;
|
||||
}
|
||||
@@ -418,6 +432,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
* @see DefaultBindingErrorProcessor
|
||||
*/
|
||||
public void setBindingErrorProcessor(BindingErrorProcessor bindingErrorProcessor) {
|
||||
Assert.notNull(bindingErrorProcessor, "BindingErrorProcessor must not be null");
|
||||
this.bindingErrorProcessor = bindingErrorProcessor;
|
||||
}
|
||||
|
||||
@@ -428,6 +443,31 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
return this.bindingErrorProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the FormatterRegistry to use for obtaining Formatters in preference
|
||||
* to JavaBeans PropertyEditors.
|
||||
*/
|
||||
public void setFormatterRegistry(FormatterRegistry formatterRegistry) {
|
||||
this.formatterRegistry = formatterRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FormatterRegistry to use for obtaining Formatters in preference
|
||||
* to JavaBeans PropertyEditors.
|
||||
* @return the FormatterRegistry (never <code>null</code>), which may also be
|
||||
* used to register further Formatters for this DataBinder
|
||||
*/
|
||||
public FormatterRegistry getFormatterRegistry() {
|
||||
if (this.formatterRegistry == null) {
|
||||
this.formatterRegistry = new GenericFormatterRegistry();
|
||||
}
|
||||
else if (this.formatterRegistry instanceof GenericFormatterRegistry &&
|
||||
((GenericFormatterRegistry) this.formatterRegistry).isShared()) {
|
||||
this.formatterRegistry = ((GenericFormatterRegistry) this.formatterRegistry).clone();
|
||||
}
|
||||
return this.formatterRegistry;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of PropertyEditorRegistry/TypeConverter interface
|
||||
|
||||
Reference in New Issue
Block a user