geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From strub...@apache.org
Subject svn commit: r1804397 - in /geronimo/components/config/trunk: ./ impl/ impl/src/main/java/org/apache/geronimo/config/cdi/ impl/src/test/java/org/apache/geronimo/config/test/internal/
Date Tue, 08 Aug 2017 10:55:56 GMT
Author: struberg
Date: Tue Aug  8 10:55:56 2017
New Revision: 1804397

URL: http://svn.apache.org/viewvc?rev=1804397&view=rev
Log:
GERONIMO-6577 move back to a more dynamic version

The goal of r1800748 to calculate all information upfront could not be achieved
so we move back to the old version

Modified:
    geronimo/components/config/trunk/impl/debug-suite.xml
    geronimo/components/config/trunk/impl/pom.xml
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
    geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
    geronimo/components/config/trunk/pom.xml

Modified: geronimo/components/config/trunk/impl/debug-suite.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/debug-suite.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/debug-suite.xml (original)
+++ geronimo/components/config/trunk/impl/debug-suite.xml Tue Aug  8 10:55:56 2017
@@ -24,7 +24,7 @@
     <classes>
         <!-- Issues in the spec -->
         <!-- CDI-437 -->
-        <class name="org.eclipse.microprofile.config.tck.CdiOptionalInjectionTest">
+        <class name="org.eclipse.microprofile.config.tck.CDIPlainInjectionTest">
             <methods>
                 <include name=".*"/>
             </methods>

Modified: geronimo/components/config/trunk/impl/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/pom.xml (original)
+++ geronimo/components/config/trunk/impl/pom.xml Tue Aug  8 10:55:56 2017
@@ -27,7 +27,6 @@
     </parent>
 
     <artifactId>geronimo-config-impl</artifactId>
-    <name>Geronimo Microprofile Configuration :: Implementation</name>
 
     <dependencyManagement>
         <dependencies>

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
(original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
Tue Aug  8 10:55:56 2017
@@ -16,54 +16,38 @@
  */
 package org.apache.geronimo.config.cdi;
 
-import org.apache.geronimo.config.ConfigImpl;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
 
-import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.event.Observes;
 import javax.enterprise.inject.spi.AfterBeanDiscovery;
 import javax.enterprise.inject.spi.AfterDeploymentValidation;
-import javax.enterprise.inject.spi.AnnotatedMember;
-import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.BeanManager;
-import javax.enterprise.inject.spi.BeforeBeanDiscovery;
 import javax.enterprise.inject.spi.BeforeShutdown;
+import javax.enterprise.inject.spi.DeploymentException;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.InjectionPoint;
 import javax.enterprise.inject.spi.ProcessInjectionPoint;
 import javax.inject.Provider;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.BiFunction;
-import java.util.stream.Stream;
 
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toMap;
-import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
+import org.apache.geronimo.config.DefaultConfigProvider;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
  */
 public class ConfigExtension implements Extension {
-    private static final Object NULL = new Object();
-
     private Config config;
-    private ConfigProviderResolver resolver;
 
-    private Set<Injection> injections = new HashSet<>();
-    private List<Throwable> deploymentProblems = new ArrayList<>();
     private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
 
     static {
@@ -74,336 +58,65 @@ public class ConfigExtension implements
         REPLACED_TYPES.put(boolean.class, Boolean.class);
     }
 
-    void init(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager
bm) {
-        resolver = ConfigProviderResolver.instance();
-        config = getConfig();
-    }
+    private Set<InjectionPoint> injectionPoints = new HashSet<>();
+
 
     public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
-        final InjectionPoint injectionPoint = pip.getInjectionPoint();
-        final ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
+        ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
         if (configProperty != null) {
-            Type replacedType = REPLACED_TYPES.getOrDefault(injectionPoint.getType(), injectionPoint.getType());
-            Injection injection = new Injection(replacedType);
-            final String key = getConfigKey(injectionPoint, configProperty);
-            final boolean defaultUnset = isDefaultUnset(configProperty.defaultValue());
-            if (!injections.add(injection)) {
-                final Injection ref = injection;
-                injection = injections.stream().filter(i -> i.equals(ref)).findFirst().get();
-            }
-            injection.keys.add(key);
-            injection.defaultValues.add(configProperty.defaultValue());
-
-            final ConfigImpl configImpl = unwrapConfig();
-
-            // what about lazy runtime lookup, not consistent with tck and system prop usage,
for now assume optional=optional ;)
-            boolean hasValue = true;
-            if (defaultUnset) { // value validation
-                if (ParameterizedType.class.isInstance(injection.type)) {
-                    final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
-                    if (pt.getRawType() != Optional.class && !configImpl.getOptionalValue(key,
String.class).isPresent()) {
-                        hasValue = false;
-                    }
-                } else if (!configImpl.getOptionalValue(key, String.class).isPresent()) {
-                    hasValue = false;
-                }
-                if (!hasValue) {
-                    deploymentProblems.add(new IllegalArgumentException("No configured value
for '" + key + "' from " + injectionPoint));
-                }
-            }
-
-            Class<?> instanceType = null;
-            if (ParameterizedType.class.isInstance(injection.type)) { // converters validation
-                final ParameterizedType pt = ParameterizedType.class.cast(injection.type);
-                if (pt.getRawType() == Provider.class && pt.getActualTypeArguments().length
== 1 && Class.class.isInstance(pt.getActualTypeArguments()[0])
-                        && !configImpl.getConverters().containsKey(Class.class.cast(pt.getActualTypeArguments()[0])))
{
-                    instanceType = Class.class.cast(pt.getActualTypeArguments()[0]);
-                } // else if Optional it is fine, else we don't know how to process
-            } else if (Class.class.isInstance(injection.type)) {
-                instanceType = Class.class.cast(injection.type);
-            }
-            if (instanceType != null) { // validate we have a converter + we can convert
the existing value
-                if (!configImpl.getConverters().containsKey(instanceType)) {
-                    deploymentProblems.add(new IllegalArgumentException("Missing converter
for '" + key + "' from " + injectionPoint));
-                } else if (hasValue) {
-                    try {
-                        configImpl.getConverters().get(injection.type).convert(configImpl.getValue(key));
-                    } catch (final RuntimeException re) {
-                        deploymentProblems.add(re);
-                    }
-                }
-            }
+            injectionPoints.add(pip.getInjectionPoint());
         }
     }
 
     public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm)
{
-        injections.stream()
-                .flatMap(injection -> {
-                    final BiFunction<CreationalContext<?>, ConfigInjectionBean<?>,
String> keyProvider;
-                    if (injection.keys.size() == 1) {
-                        final String key = injection.keys.iterator().next();
-                        keyProvider = (ctx, bean) -> key;
-                    } else {
-                        keyProvider = (ctx, bean) -> getName(findInjectionPoint(bm, ctx,
bean));
-                    }
-
-                    if (ParameterizedType.class.isInstance(injection.type)) {
-                        final ParameterizedType paramType = ParameterizedType.class.cast(injection.type);
-                        final Type rawType = paramType.getRawType();
-
-                        // todo: do we care of Instance injection? doesnt make much sense
right?
-                        if (Provider.class == rawType && paramType.getActualTypeArguments().length
== 1) {
-                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0]))
{
-                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty
can only be used with Provider<T> where T is a Class"));
-                                return Stream.empty();
-                            }
-                            final Class<?> providerType = Class.class.cast(paramType.getActualTypeArguments()[0]);
-                            return Stream.of(new ConfigInjectionBean<Provider<?>>(injection.type,
true) {
-                                @Override
-                                public Provider<?> create(final CreationalContext<Provider<?>>
context) {
-                                    return () -> config.getValue(keyProvider.apply(context,
this), providerType);
-                                }
-                            });
-                        } else if (Optional.class == rawType && paramType.getActualTypeArguments().length
== 1) {
-                            if (!Class.class.isInstance(paramType.getActualTypeArguments()[0]))
{
-                                deploymentProblems.add(new IllegalArgumentException("@ConfigProperty
can only be used with Optional<T> where T is a Class"));
-                                return null;
-                            }
-                            final Class<?> optionalType = Class.class.cast(paramType.getActualTypeArguments()[0]);
-                            return Stream.of(new ConfigInjectionBean<Optional<?>>(injection.type)
{
-                                @Override
-                                public Optional<?> create(final CreationalContext<Optional<?>>
context) {
-                                    return config.getOptionalValue(keyProvider.apply(context,
this), optionalType);
-                                }
-                            });
-                        } else {
-                            deploymentProblems.add(new IllegalArgumentException("Unsupported
parameterized type " + paramType));
-                            return Stream.empty();
-                        }
-                    } else if (Class.class.isInstance(injection.type)) {
-                        final Class clazz = Class.class.cast(injection.type);
-                        final ConfigInjectionBean bean;
-                        if (injection.defaultValues.isEmpty()) {
-                            bean = new ConfigInjectionBean<Object>(injection.type)
{
-                                @Override
-                                public Object create(final CreationalContext<Object>
context) {
-                                    return config.getOptionalValue(keyProvider.apply(context,
this), clazz);
-                                }
-                            };
-                        } else if (injection.defaultValues.size() == 1) { // common enough
to be optimized
-                            final String defVal = injection.defaultValues.iterator().next();
-                            final Object alternativeVal = isDefaultUnset(defVal) ? null :
unwrapConfig().convert(defVal, clazz);
-                            bean = new ConfigInjectionBean<Object>(injection.type)
{
-                                @Override
-                                public Object create(final CreationalContext<Object>
context) {
-                                    final Optional optionalValue = config.getOptionalValue(keyProvider.apply(context,
this), clazz);
-                                    return optionalValue.orElse(alternativeVal);
-                                }
-                            };
-                        } else { // sadly we need to get back to the injection point to know
which one we need to use
-                            final Map<String, Object> prepared = injection.defaultValues.stream()
-                                    .collect(toMap(identity(), k -> isDefaultUnset(k)
? NULL : unwrapConfig().convert(k, clazz), (a, b) -> b));
-                            bean = new ConfigInjectionBean<Object>(injection.type)
{
-                                @Override
-                                public Object create(final CreationalContext<Object>
context) {
-                                    final InjectionPoint ip = findInjectionPoint(bm, context,
this);
-                                    if (ip == null) {
-                                        throw new IllegalStateException("Could not retrieve
InjectionPoint");
-                                    }
-                                    return config.getOptionalValue(ConfigExtension.this.getName(ip),
clazz)
-                                            .orElseGet(() -> {
-                                                final Object val = prepared.get(ip.getAnnotated().getAnnotation(ConfigProperty.class).defaultValue());
-                                                return val == NULL ? null : val;
-                                            });
-                                }
-                            };
-                        }
-
-                        final Collection<ConfigInjectionBean<?>> beans = new
ArrayList<>();
-                        beans.add(bean);
-
-                        // is adding these beans is that useful? we captured them all so
only a programmatic lookup would justify it
-                        // and not sure it would be done this way anyway
-                        final ParameterizedTypeImpl providerType = new ParameterizedTypeImpl(Provider.class,
injection.type);
-                        if (injections.stream().noneMatch(i -> i.type.equals(providerType)))
{
-                            beans.add(new ConfigInjectionBean<Provider<?>>(providerType,
true) {
-                                @Override
-                                public Provider<?> create(final CreationalContext<Provider<?>>
context) {
-                                    return () -> bean.create(context);
-                                }
-                            });
-                        }
-
-                        final ParameterizedTypeImpl optionalType = new ParameterizedTypeImpl(Optional.class,
injection.type);
-                        if (injections.stream().noneMatch(i -> i.type.equals(optionalType)))
{
-                            beans.add(new ConfigInjectionBean<Optional<?>>(optionalType)
{
-                                @Override
-                                public Optional<?> create(final CreationalContext<Optional<?>>
context) {
-                                    return Optional.ofNullable(bean.create(context));
-                                }
-                            });
-                        }
-
-                        return beans.stream();
-                    } else {
-                        deploymentProblems.add(new IllegalArgumentException("Unknown type
" + injection.type));
-                        return Stream.empty();
-                    }
-                })
-                .forEach(abd::addBean);
-    }
+        Set<Class> types = injectionPoints.stream()
+                .filter(ip -> ip.getType() instanceof Class)
+                .map(ip -> (Class) REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
+                .collect(Collectors.toSet());
+
+        // Provider and Optional are ParameterizedTypes and not a Class, so we need to add
them manually
+        types.add(Provider.class);
+        types.add(Optional.class);
 
-    public void validate(@Observes AfterDeploymentValidation add) {
-        deploymentProblems.forEach(add::addDeploymentProblem);
-        injections.clear();
-        deploymentProblems.clear();
+        types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type)));
     }
 
-    public void shutdown(@Observes BeforeShutdown bsd) {
-        resolver.releaseConfig(config);
-    }
+    public void validate(@Observes AfterDeploymentValidation add) {
+        List<String> deploymentProblems = new ArrayList<>();
 
-    private ConfigImpl unwrapConfig() {
-        return ConfigImpl.class.cast(config);
-    }
+        config = ConfigProvider.getConfig();
 
-    private static String getName(final InjectionPoint ip) {
-        final ConfigProperty annotation = ip.getAnnotated().getAnnotation(ConfigProperty.class);
-        final String name = annotation.name();
-        return isDefaultUnset(name) ? getConfigKey(ip, annotation) : name;
-    }
+        for (InjectionPoint injectionPoint : injectionPoints) {
+            Type type = injectionPoint.getType();
 
-    /**
-     * Get the property key to use.
-     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key
name from the InjectionPoint.
-     */
-    private static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty)
{
-        String key = configProperty.name();
-        if (!key.isEmpty()) {
-            return key;
-        }
-        if (ip.getAnnotated() instanceof AnnotatedMember) {
-            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
-            AnnotatedType declaringType = member.getDeclaringType();
-            if (declaringType != null) {
-                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
-                String cn = parts[parts.length - 1];
-                parts[parts.length - 1] = Character.toLowerCase(cn.charAt(0)) + (cn.length()
> 1 ? cn.substring(1) : "");
-                StringBuilder sb = new StringBuilder(parts[0]);
-                for (int i = 1; i < parts.length; i++) {
-                    sb.append(".").append(parts[i]);
+            // replace native types with their Wrapper types
+            type = REPLACED_TYPES.getOrDefault(type, type);
+
+            ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
+            if (type instanceof Class) {
+                // a direct injection of a ConfigProperty
+                // that means a Converter must exist.
+                String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
+                if ((isDefaultUnset(configProperty.defaultValue()))
+                        && !config.getOptionalValue(key, (Class) type).isPresent())
{
+                    deploymentProblems.add("No Config Value exists for " + key);
                 }
-
-                // now add the field name
-                sb.append(".").append(member.getJavaMember().getName());
-                return sb.toString();
             }
         }
 
-        throw new IllegalStateException("Could not find default name for @ConfigProperty
InjectionPoint " + ip);
-    }
-
-    private static boolean isDefaultUnset(String defaultValue) {
-        return defaultValue == null || defaultValue.length() == 0 || defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
-    }
-
-    private static InjectionPoint findInjectionPoint(final BeanManager bm, final CreationalContext<?>
ctx,
-                                                     ConfigInjectionBean bean) {
-        return InjectionPoint.class.cast(bm.getInjectableReference(bean.getSimpleInjectionPoint(),
ctx));
-    }
-
-    private static final class Injection {
-        private final Type type;
-        private final Collection<String> keys = new ArrayList<>();
-        private final Collection<String> defaultValues = new ArrayList<>();
-
-        private Injection(final Type type) {
-            this.type = type;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || Injection.class != o.getClass()) {
-                return false;
-            }
-            final Injection injection = Injection.class.cast(o);
-            return Objects.equals(type, injection.type);
+        if (!deploymentProblems.isEmpty()) {
+            add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n"
+                                                             + String.join("\n", deploymentProblems)));
         }
 
-        @Override
-        public int hashCode() {
-            return type.hashCode();
-        }
     }
 
-    private class ParameterizedTypeImpl implements ParameterizedType {
-        private final Type rawType;
-        private final Type[] types;
-
-        private ParameterizedTypeImpl(final Type raw, final Type... types) {
-            this.rawType = raw;
-            this.types = types;
-        }
-
-        @Override
-        public Type[] getActualTypeArguments() {
-            return types.clone();
-        }
-
-        @Override
-        public Type getOwnerType() {
-            return null;
-        }
-
-        @Override
-        public Type getRawType() {
-            return rawType;
-        }
-
-        @Override
-        public int hashCode() {
-            return Arrays.hashCode(types) ^ rawType.hashCode();
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (ParameterizedType.class.isInstance(obj)) {
-                final ParameterizedType that = ParameterizedType.class.cast(obj);
-                final Type thatRawType = that.getRawType();
-                return (rawType == null ? thatRawType == null : rawType.equals(thatRawType))
-                        && Arrays.equals(types, that.getActualTypeArguments());
-            }
-            return false;
-        }
+    public void shutdown(@Observes BeforeShutdown bsd) {
+        DefaultConfigProvider.instance().releaseConfig(config);
+    }
 
-        @Override
-        public String toString() {
-            final StringBuilder buffer = new StringBuilder();
-            buffer.append(Class.class.cast(rawType).getName());
-            final Type[] actualTypes = getActualTypeArguments();
-            if (actualTypes.length > 0) {
-                buffer.append("<");
-                final int length = actualTypes.length;
-                for (int i = 0; i < length; i++) {
-                    if (actualTypes[i] instanceof Class) {
-                        buffer.append(((Class<?>) actualTypes[i]).getSimpleName());
-                    } else {
-                        buffer.append(actualTypes[i].toString());
-                    }
-                    if (i != actualTypes.length - 1) {
-                        buffer.append(",");
-                    }
-                }
 
-                buffer.append(">");
-            }
-            return buffer.toString();
-        }
+    static boolean isDefaultUnset(String defaultValue) {
+        return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
     }
 }

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
(original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
Tue Aug  8 10:55:56 2017
@@ -16,49 +16,59 @@
  */
 package org.apache.geronimo.config.cdi;
 
-import org.eclipse.microprofile.config.inject.ConfigProperty;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
 
 import javax.enterprise.context.Dependent;
 import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.Default;
 import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedMember;
+import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.InjectionPoint;
 import javax.enterprise.inject.spi.PassivationCapable;
 import javax.enterprise.util.AnnotationLiteral;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import javax.inject.Provider;
+
+import org.apache.geronimo.config.ConfigImpl;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
  */
-public abstract class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable
{
+public class ConfigInjectionBean<T> implements Bean<T>, PassivationCapable {
 
     private final static Set<Annotation> QUALIFIERS = new HashSet<>();
     static {
         QUALIFIERS.add(new ConfigPropertyLiteral());
     }
 
+    private final BeanManager bm;
     private final Class rawType;
     private final Set<Type> types;
-    private final String id;
-    private final boolean alternative;
-
-    ConfigInjectionBean(Type type) {
-        this(type,false);
-    }
 
-    ConfigInjectionBean(Type type, boolean alternative) {
-        this.types = new HashSet<>();
-        this.types.add(type);
-        this.rawType = getRawType(type);
-        this.id = "ConfigInjectionBean_" + type.toString();
-        this.alternative = alternative;
+    /**
+     * only access via {@link #getConfig(}
+     */
+    private Config _config;
+
+    public ConfigInjectionBean(BeanManager bm, Type type) {
+        this.bm = bm;
+
+        types = new HashSet<>();
+        types.add(type);
+        rawType = getRawType(type);
     }
 
     private Class getRawType(Type type) {
@@ -76,7 +86,7 @@ public abstract class ConfigInjectionBea
 
     @Override
     public Set<InjectionPoint> getInjectionPoints() {
-        return Collections.emptySet();
+        return Collections.EMPTY_SET;
     }
 
     @Override
@@ -90,8 +100,90 @@ public abstract class ConfigInjectionBea
     }
 
     @Override
+    public T create(CreationalContext<T> context) {
+        Set<Bean<?>> beans = bm.getBeans(InjectionPoint.class);
+        Bean<?> bean = bm.resolve(beans);
+        InjectionPoint ip = (InjectionPoint) bm.getReference(bean, InjectionPoint.class,
 context);
+        if (ip == null) {
+            throw new IllegalStateException("Could not retrieve InjectionPoint");
+        }
+        Annotated annotated = ip.getAnnotated();
+        ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class);
+        String key = getConfigKey(ip, configProperty);
+        String defaultValue = configProperty.defaultValue();
+
+        if (annotated.getBaseType() instanceof ParameterizedType) {
+            ParameterizedType paramType = (ParameterizedType) annotated.getBaseType();
+            Type rawType = paramType.getRawType();
+
+            // handle Provider<T>
+            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class)
&& paramType.getActualTypeArguments().length == 1) {
+                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check
type again, etc
+                return (T) new ConfigValueProvider(getConfig(), key, clazz);
+            }
+
+            // handle Optional<T>
+            if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Optional.class)
&& paramType.getActualTypeArguments().length == 1) {
+                Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check
type again, etc
+                return (T) getConfig().getOptionalValue(key, clazz);
+            }
+        }
+        else {
+            Class clazz = (Class) annotated.getBaseType();
+            if (ConfigExtension.isDefaultUnset(defaultValue)) {
+                return (T) getConfig().getValue(key, clazz);
+            }
+            else {
+                Config config = getConfig();
+                return (T) config.getOptionalValue(key, clazz)
+                        .orElse(((ConfigImpl) config).convert(defaultValue, clazz));
+            }
+        }
+
+        throw new IllegalStateException("unhandled ConfigProperty");
+    }
+
+
+    /**
+     * Get the property key to use.
+     * In case the {@link ConfigProperty#name()} is empty we will try to determine the key
name from the InjectionPoint.
+     */
+    public static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) {
+        String key = configProperty.name();
+        if (key.length() > 0) {
+            return key;
+        }
+        if (ip.getAnnotated() instanceof AnnotatedMember) {
+            AnnotatedMember member = (AnnotatedMember) ip.getAnnotated();
+            AnnotatedType declaringType = member.getDeclaringType();
+            if (declaringType != null) {
+                String[] parts = declaringType.getJavaClass().getCanonicalName().split("\\.");
+                String cn = parts[parts.length-1];
+                parts[parts.length-1] = Character.toLowerCase(cn.charAt(0)) + (cn.length()
> 1 ? cn.substring(1) : "");
+                StringBuilder sb = new StringBuilder(parts[0]);
+                for (int i = 1; i < parts.length; i++) {
+                    sb.append(".").append(parts[i]);
+                }
+
+                // now add the field name
+                sb.append(".").append(member.getJavaMember().getName());
+                return sb.toString();
+            }
+        }
+
+        throw new IllegalStateException("Could not find default name for @ConfigProperty
InjectionPoint " + ip);
+    }
+
+    public Config getConfig() {
+        if (_config == null) {
+            _config = ConfigProvider.getConfig();
+        }
+        return _config;
+    }
+
+    @Override
     public void destroy(T instance, CreationalContext<T> context) {
-        // no-op
+
     }
 
     @Override
@@ -116,21 +208,17 @@ public abstract class ConfigInjectionBea
 
     @Override
     public Set<Class<? extends Annotation>> getStereotypes() {
-        return Collections.emptySet();
+        return Collections.EMPTY_SET;
     }
 
     @Override
     public boolean isAlternative() {
-        return alternative;
+        return true;
     }
 
     @Override
     public String getId() {
-        return id;
-    }
-
-    InjectionPoint getSimpleInjectionPoint() {
-        return simpleInjectionPoint;
+        return "ConfigInjectionBean_" + rawType.getName();
     }
 
     private static class ConfigPropertyLiteral extends AnnotationLiteral<ConfigProperty>
implements ConfigProperty {
@@ -145,41 +233,31 @@ public abstract class ConfigInjectionBea
         }
     }
 
-    private final InjectionPoint simpleInjectionPoint = new InjectionPoint() {
-
-        @Override
-        public boolean isTransient() {
-            return false;
-        }
-
-        @Override
-        public boolean isDelegate() {
-            return false;
-        }
-
-        @Override
-        public Type getType() {
-            return InjectionPoint.class;
-        }
-
-        @Override
-        public Set<Annotation> getQualifiers() {
-            return Collections.singleton(new AnnotationLiteral<Default>() {});
-        }
-
-        @Override
-        public Member getMember() {
-            return null;
+    /**
+     * A special Provider&lt;T&gt;
+     * This concrete class is needed because we need the injected Provider for the ConfigProperty
+     * to be Serializable. A Lambda would not work in this case
+     */
+    public static class ConfigValueProvider<T> implements Provider<T>, Serializable
{
+        private transient Config config;
+        private final String key;
+        private final Class<T> type;
+
+        ConfigValueProvider(Config config, String key, Class<T> type) {
+            this.config = config;
+            this.key = key;
+            this.type = type;
         }
 
         @Override
-        public Bean<?> getBean() {
-            return ConfigInjectionBean.this;
+        public T get() {
+            return (T) config.getValue(key, type);
+        }
+
+        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
{
+            in.defaultReadObject();
+            config = ConfigProviderResolver.instance().getConfig();
         }
 
-        @Override
-        public Annotated getAnnotated() {
-            return null;
-        }
-    };
+    }
 }

Modified: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
(original)
+++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
Tue Aug  8 10:55:56 2017
@@ -33,9 +33,12 @@ import org.testng.annotations.Test;
 
 public class ProviderTest extends Arquillian {
     private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
+    private static final String ANOTHER_KEY = "org.apache.geronimo.config.test.internal.anotherkey";
 
     @Deployment
     public static WebArchive deploy() {
+        System.setProperty(SOME_KEY, "someval");
+        System.setProperty(ANOTHER_KEY, "someval");
         JavaArchive testJar = ShrinkWrap
                 .create(JavaArchive.class, "configProviderTest.jar")
                 .addClasses(ProviderTest.class, SomeBean.class)
@@ -70,8 +73,16 @@ public class ProviderTest extends Arquil
         @ConfigProperty(name=SOME_KEY)
         private Provider<String> myconfig;
 
+        @Inject
+        @ConfigProperty(name=ANOTHER_KEY)
+        private Provider<String> anotherconfig;
+
         public String getMyconfig() {
             return myconfig.get();
         }
+
+        public Provider<String> getAnotherconfig() {
+            return anotherconfig;
+        }
     }
 }

Modified: geronimo/components/config/trunk/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/pom.xml?rev=1804397&r1=1804396&r2=1804397&view=diff
==============================================================================
--- geronimo/components/config/trunk/pom.xml (original)
+++ geronimo/components/config/trunk/pom.xml Tue Aug  8 10:55:56 2017
@@ -27,7 +27,7 @@
     </parent>
 
     <groupId>org.apache.geronimo.config</groupId>
-    <artifactId>config-parent</artifactId>
+    <artifactId>geronimo-config</artifactId>
     <version>1.1-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Geronimo Microprofile Configuration</name>
@@ -50,7 +50,7 @@
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <microprofile-config.version>1.1-SNAPSHOT</microprofile-config.version>
+        <microprofile-config.version>1.0</microprofile-config.version>
         <owb.version>1.7.3</owb.version>
         <owb2.version>2.0.1-SNAPSHOT</owb2.version>
         <arquillian.version>1.1.13.Final</arquillian.version>



Mime
View raw message