Repository: deltaspike Updated Branches: refs/heads/master 5685edbf5 -> 7b55ff21d
DELTASPIKE-1303 List/Set support for @Configuration proxy based interfaces Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/7b55ff21 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/7b55ff21 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/7b55ff21 Branch: refs/heads/master Commit: 7b55ff21da633b11ac84a6526fce0b64473ca669 Parents: 5685edb Author: Romain Manni-Bucau <rmannibu...@gmail.com> Authored: Wed Nov 29 11:30:01 2017 +0100 Committer: Romain Manni-Bucau <rmannibu...@gmail.com> Committed: Wed Nov 29 11:30:01 2017 +0100 ---------------------------------------------------------------------- .../core/api/config/ConfigResolver.java | 13 +- .../config/ProxyConfigurationLifecycle.java | 171 +++++++++++++++---- .../core/api/config/injectable/ConfigBean.java | 7 + .../InjectableConfigPropertyTest.java | 3 + 4 files changed, 159 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java index f3f8743..9082584 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java @@ -915,7 +915,14 @@ public final class ConfigResolver + keyOriginal); } - defaultValue = convert(value); + if (isList) + { + defaultValue = splitAndConvertListValue(value); + } + else + { + defaultValue = convert(value); + } withDefault = true; return this; } @@ -1006,6 +1013,10 @@ public final class ConfigResolver .setEvaluateVariables(evaluateVariables) .setProjectStageAware(projectStageAware); value = fallbackToDefaultIfEmpty(keyResolved, value, defaultValue, configResolverContext); + if (isList && String.class.isInstance(value)) + { + value = splitAndConvertListValue(String.class.cast(value)); + } } if (logChanges && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java index 13c687e..4387a11 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java @@ -29,7 +29,12 @@ import javax.enterprise.inject.spi.Bean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; +import java.lang.reflect.Type; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -72,8 +77,8 @@ class ProxyConfigurationLifecycle implements ContextualLifecycle { }; - private final ConcurrentMap<Method, ConfigResolver.TypedResolver<?>> resolvers = - new ConcurrentHashMap<Method, ConfigResolver.TypedResolver<?>>(); + private final ConcurrentMap<Method, Supplier<?>> resolvers = + new ConcurrentHashMap<Method, Supplier<?>>(); private final long cacheMs; private final String prefix; @@ -98,8 +103,8 @@ class ProxyConfigurationLifecycle implements ContextualLifecycle } } - ConfigResolver.TypedResolver<?> typedResolver = resolvers.get(method); - if (typedResolver == null) + Supplier<?> supplier = resolvers.get(method); + if (supplier == null) { final ConfigProperty annotation = method.getAnnotation(ConfigProperty.class); if (annotation == null) @@ -109,52 +114,150 @@ class ProxyConfigurationLifecycle implements ContextualLifecycle } // handle primitive bridge there (cdi doesnt support primitives but no reason our proxies don't) + final Class<? extends ConfigResolver.Converter> converter = annotation.converter(); + + final Type genericReturnType = method.getGenericReturnType(); Class<?> returnType = method.getReturnType(); - if (int.class == returnType) - { - returnType = Integer.class; - } - else if (long.class == returnType) - { - returnType = Long.class; - } - else if (boolean.class == returnType) - { - returnType = Boolean.class; - } - else if (short.class == returnType) - { - returnType = Short.class; - } - else if (byte.class == returnType) - { - returnType = Byte.class; - } - else if (float.class == returnType) + final boolean list; + final boolean set; + if (converter == ConfigResolver.Converter.class && + ParameterizedType.class.isInstance(genericReturnType)) { - returnType = Float.class; + ParameterizedType pt = ParameterizedType.class.cast(genericReturnType); + if (List.class == pt.getRawType() && pt.getActualTypeArguments().length == 1) + { + list = true; + set = false; + final Type arg = pt.getActualTypeArguments()[0]; + if (Class.class.isInstance(arg)) + { + returnType = Class.class.cast(arg); + } + } + else if (Set.class == pt.getRawType() && pt.getActualTypeArguments().length == 1) + { + list = false; + set = true; + final Type arg = pt.getActualTypeArguments()[0]; + if (Class.class.isInstance(arg)) + { + returnType = Class.class.cast(arg); + } + } + else + { + list = false; + set = false; + } } - else if (double.class == returnType) + else { - returnType = Double.class; + list = false; + set = false; + + if (int.class == returnType) + { + returnType = Integer.class; + } + else if (long.class == returnType) + { + returnType = Long.class; + } + else if (boolean.class == returnType) + { + returnType = Boolean.class; + } + else if (short.class == returnType) + { + returnType = Short.class; + } + else if (byte.class == returnType) + { + returnType = Byte.class; + } + else if (float.class == returnType) + { + returnType = Float.class; + } + else if (double.class == returnType) + { + returnType = Double.class; + } } - typedResolver = delegate.asResolver( - prefix + annotation.name(), annotation.defaultValue(), returnType, - annotation.converter(), annotation.parameterizedBy(), + final String defaultValue = annotation.defaultValue(); + ConfigResolver.TypedResolver<?> typedResolver = delegate.asResolver( + prefix + annotation.name(), list || set ? ConfigProperty.NULL : defaultValue, + returnType, converter, annotation.parameterizedBy(), annotation.projectStageAware(), annotation.evaluateVariables()); + if (cacheMs > 0) { typedResolver.cacheFor(MILLISECONDS, cacheMs); } - final ConfigResolver.TypedResolver<?> existing = resolvers.putIfAbsent(method, typedResolver); + if (list || set) + { + ConfigResolver.TypedResolver<? extends List<?>> listTypedResolver = typedResolver.asList(); + final ConfigResolver.TypedResolver<? extends List<?>> resolver; + if (!ConfigProperty.NULL.equals(defaultValue)) + { + resolver = listTypedResolver.withStringDefault(defaultValue); + } + else + { + resolver = listTypedResolver; + } + + if (list) + { + supplier = new DefaultSupplier(resolver); + } + else + { + supplier = new Supplier<Set<?>>() + { + @Override + public Set<?> get() + { + return new HashSet(resolver.getValue()); + } + }; + } + } + else + { + supplier = new DefaultSupplier(typedResolver); + } + + final Supplier<?> existing = resolvers.putIfAbsent(method, supplier); if (existing != null) { - typedResolver = existing; + supplier = existing; } } - return typedResolver.getValue(); + return supplier.get(); + } + } + + private interface Supplier<T> + { + T get(); + } + + private static class DefaultSupplier<T> implements Supplier<T> + { + private final ConfigResolver.TypedResolver<T> delegate; + + private DefaultSupplier(final ConfigResolver.TypedResolver<T> delegate) + { + this.delegate = delegate; + } + + @Override + public T get() + { + return delegate.getValue(); } } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java index 40bcb45..8157f26 100644 --- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java +++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java @@ -23,6 +23,7 @@ import org.apache.deltaspike.core.api.config.Configuration; import java.net.URL; import java.util.List; +import java.util.Set; @Configuration public interface ConfigBean @@ -72,6 +73,12 @@ public interface ConfigBean @ConfigProperty(name = "testDbConfig") String dbConfig(); + @ConfigProperty(name = "defaultList", defaultValue = "http://localhost,http://127.0.0.1") + List<String> defaultListHandling(); + + @ConfigProperty(name = "defaultSet", defaultValue = "1,2") + Set<Integer> defaultSetHandling(); + @ConfigProperty(name = "urlList", converter = SettingsBean.UrlList.class, defaultValue = "http://localhost,http://127.0.0.1") List<URL> urlList(); http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java index 5009949..ec74c1a 100644 --- a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java +++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java @@ -20,6 +20,7 @@ package org.apache.deltaspike.test.core.api.config.injectable; import java.net.MalformedURLException; import java.net.URL; +import java.util.HashSet; import org.apache.deltaspike.core.api.provider.BeanProvider; import org.apache.deltaspike.test.category.SeCategory; @@ -146,6 +147,8 @@ public class InjectableConfigPropertyTest assertEquals(Boolean.TRUE, settingsBean.booleanPropertyTrue7()); assertEquals(Boolean.TRUE, settingsBean.booleanPropertyTrue8()); assertEquals(asList(new URL("http://localhost"), new URL("http://127.0.0.1")), settingsBean.urlList()); + assertEquals(asList("http://localhost", "http://127.0.0.1"), settingsBean.defaultListHandling()); + assertEquals(new HashSet<Integer>(asList(1, 2)), settingsBean.defaultSetHandling()); assertEquals(singletonList(new URL("http://127.0.0.2")), settingsBean.urlListFromProperties()); assertEquals("value", settingsBean.customSourceValue()); }