Bugfix: autoresolving boxed types from native types for resolver lookup.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/42175ba7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/42175ba7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/42175ba7 Branch: refs/heads/master Commit: 42175ba782f92c3798f8c858fcf18b1d9b3fa423 Parents: 52e1d1f Author: anatole <anat...@apache.org> Authored: Tue Mar 24 15:52:56 2015 +0100 Committer: anatole <anat...@apache.org> Committed: Tue Mar 24 15:52:56 2015 +0100 ---------------------------------------------------------------------- .../core/internal/PropertyConverterManager.java | 96 +++++++++++++++++--- .../core/internal/PropertyConverterManager.java | 89 +++++++++++++++--- 2 files changed, 159 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/42175ba7/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java index dccd2dd..c93e84d 100644 --- a/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java @@ -21,7 +21,6 @@ package org.apache.tamaya.core.internal; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; @@ -51,12 +50,17 @@ public class PropertyConverterManager { private Map<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>(); /** The lock used. */ private StampedLock lock = new StampedLock(); - private static final String CHAR_NULL_ERROR = "Cannot convert null property"; /** * Constructor. */ public PropertyConverterManager() { - initConverters(); + this(true); + } + + public PropertyConverterManager(boolean init) { + if (init) { + initConverters(); + } } /** @@ -64,14 +68,8 @@ public class PropertyConverterManager { */ protected void initConverters() { for(PropertyConverter conv: ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)){ - ParameterizedType type = ReflectionUtil.getParametrizedType(conv.getClass()); - if(type==null || type.getActualTypeArguments().length==0){ - LOG.warning("Failed to register PropertyConverter, no generic type information available: " + - conv.getClass().getName()); - } else { - Type targetType = type.getActualTypeArguments()[0]; - register(TypeLiteral.of(targetType), conv); - } + Type type = TypeLiteral.getTypeParameter(conv.getClass(), PropertyConverter.class); + register(TypeLiteral.of(type), conv); } } @@ -80,13 +78,14 @@ public class PropertyConverterManager { * * @param targetType the target type, not null. * @param converter the converter, not null. + * @param <T> the type. */ - public void register(TypeLiteral<?> targetType, PropertyConverter<?> converter) { + public <T> void register(TypeLiteral<T> targetType, PropertyConverter<T> converter) { Objects.requireNonNull(converter); Lock writeLock = lock.asWriteLock(); try { writeLock.lock(); - List converters = List.class.cast(this.converters.get(targetType)); + List<PropertyConverter<T>> converters = List.class.cast(this.converters.get(targetType)); List<PropertyConverter<?>> newConverters = new ArrayList<>(); if (converters != null) { newConverters.addAll(converters); @@ -149,6 +148,18 @@ public class PropertyConverterManager { if (converters != null) { return converters; } + TypeLiteral<T> boxedType = mapBoxedType(targetType); + if(boxedType!=null){ + try { + readLock.lock(); + converters = List.class.cast(this.converters.get(boxedType)); + } finally { + readLock.unlock(); + } + if (converters != null) { + return converters; + } + } PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType); if (defaultConverter != null) { register(targetType, defaultConverter); @@ -166,6 +177,65 @@ public class PropertyConverterManager { } /** + * Maps native types to the corresponding boxed types. + * @param targetType the native type. + * @param <T> the type + * @return the boxed type, or null. + */ + private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) { + Type parameterType = targetType.getType(); + if(parameterType == int.class){ + return TypeLiteral.of(Integer.class); + } + if(parameterType == short.class){ + return TypeLiteral.of(Short.class); + } + if(parameterType == byte.class){ + return TypeLiteral.of(Byte.class); + } + if(parameterType == long.class){ + return TypeLiteral.of(Long.class); + } + if(parameterType == boolean.class){ + return TypeLiteral.of(Boolean.class); + } + if(parameterType == char.class){ + return TypeLiteral.of(Character.class); + } + if(parameterType == float.class){ + return TypeLiteral.of(Float.class); + } + if(parameterType == double.class){ + return TypeLiteral.of(Double.class); + } + if(parameterType == int[].class){ + return TypeLiteral.of(Integer[].class); + } + if(parameterType == short[].class){ + return TypeLiteral.of(Short[].class); + } + if(parameterType == byte[].class){ + return TypeLiteral.of(Byte[].class); + } + if(parameterType == long[].class){ + return TypeLiteral.of(Long[].class); + } + if(parameterType == boolean.class){ + return TypeLiteral.of(Boolean.class); + } + if(parameterType == char[].class){ + return TypeLiteral.of(Character[].class); + } + if(parameterType == float[].class){ + return TypeLiteral.of(Float[].class); + } + if(parameterType == double[].class){ + return TypeLiteral.of(Double[].class); + } + return null; + } + + /** * Creates a dynamic PropertyConverter for the given target type. * * @param targetType the target type http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/42175ba7/java8/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java ---------------------------------------------------------------------- diff --git a/java8/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/java8/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java index 4709ad0..fe62dc3 100644 --- a/java8/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java +++ b/java8/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java @@ -21,7 +21,6 @@ package org.apache.tamaya.core.internal; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; @@ -38,7 +37,7 @@ import org.apache.tamaya.ConfigException; import org.apache.tamaya.TypeLiteral; import org.apache.tamaya.core.internal.converters.EnumConverter; import org.apache.tamaya.PropertyConverter; -import org.apache.tamaya.spi.ServiceContext; +import org.apache.tamaya.spi.ServiceContextManager; /** * Manager that deals with {@link org.apache.tamaya.PropertyConverter} instances. @@ -51,7 +50,6 @@ public class PropertyConverterManager { private Map<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>(); /** The lock used. */ private StampedLock lock = new StampedLock(); - private static final String CHAR_NULL_ERROR = "Cannot convert null property"; /** * Constructor. */ @@ -69,15 +67,9 @@ public class PropertyConverterManager { * Registers the default converters provided out of the box. */ protected void initConverters() { - for(PropertyConverter conv: ServiceContext.getInstance().getServices(PropertyConverter.class)){ - ParameterizedType type = ReflectionUtil.getParametrizedType(conv.getClass()); - if(type==null || type.getActualTypeArguments().length==0){ - LOG.warning(() -> "Failed to register PropertyConverter, no generic type information available: " + - conv.getClass().getName()); - } else { - Type targetType = type.getActualTypeArguments()[0]; - register(TypeLiteral.of(targetType), conv); - } + for(PropertyConverter conv: ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)){ + Type type = TypeLiteral.getTypeParameter(conv.getClass(), PropertyConverter.class); + register(TypeLiteral.of(type), conv); } } @@ -156,6 +148,18 @@ public class PropertyConverterManager { if (converters != null) { return converters; } + TypeLiteral<T> boxedType = mapBoxedType(targetType); + if(boxedType!=null){ + try { + readLock.lock(); + converters = List.class.cast(this.converters.get(boxedType)); + } finally { + readLock.unlock(); + } + if (converters != null) { + return converters; + } + } PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType); if (defaultConverter != null) { register(targetType, defaultConverter); @@ -173,6 +177,65 @@ public class PropertyConverterManager { } /** + * Maps native types to the corresponding boxed types. + * @param targetType the native type. + * @param <T> the type + * @return the boxed type, or null. + */ + private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) { + Type parameterType = targetType.getType(); + if(parameterType == int.class){ + return TypeLiteral.of(Integer.class); + } + if(parameterType == short.class){ + return TypeLiteral.of(Short.class); + } + if(parameterType == byte.class){ + return TypeLiteral.of(Byte.class); + } + if(parameterType == long.class){ + return TypeLiteral.of(Long.class); + } + if(parameterType == boolean.class){ + return TypeLiteral.of(Boolean.class); + } + if(parameterType == char.class){ + return TypeLiteral.of(Character.class); + } + if(parameterType == float.class){ + return TypeLiteral.of(Float.class); + } + if(parameterType == double.class){ + return TypeLiteral.of(Double.class); + } + if(parameterType == int[].class){ + return TypeLiteral.of(Integer[].class); + } + if(parameterType == short[].class){ + return TypeLiteral.of(Short[].class); + } + if(parameterType == byte[].class){ + return TypeLiteral.of(Byte[].class); + } + if(parameterType == long[].class){ + return TypeLiteral.of(Long[].class); + } + if(parameterType == boolean.class){ + return TypeLiteral.of(Boolean.class); + } + if(parameterType == char[].class){ + return TypeLiteral.of(Character[].class); + } + if(parameterType == float[].class){ + return TypeLiteral.of(Float[].class); + } + if(parameterType == double[].class){ + return TypeLiteral.of(Double[].class); + } + return null; + } + + /** * Creates a dynamic PropertyConverter for the given target type. * * @param targetType the target type @@ -181,7 +244,7 @@ public class PropertyConverterManager { */ protected <T> PropertyConverter<T> createDefaultPropertyConverter(TypeLiteral<T> targetType) { if(Enum.class.isAssignableFrom(targetType.getRawType())){ - return new EnumConverter<T>(targetType.getRawType()); + return new EnumConverter<>(targetType.getRawType()); } PropertyConverter<T> converter = null; Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse");