You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by st...@apache.org on 2017/08/08 10:55:56 UTC
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/
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<T>
+ * 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>
Re: 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/
Posted by Mark Struberg <st...@yahoo.de>.
I'll take a look in the evening.
LieGrue,
Strub
> Am 09.08.2017 um 14:00 schrieb John D. Ament <jo...@apache.org>:
>
> Ok, I got tests passing on all three. It actually looks like its simpler (and more correct) to not use a custom provider. The provider approach wasn't supporting default values. I've committed changes, please take a look and hopefully we can plan to reroll 1.0.
>
> John
>
>> On Tue, Aug 8, 2017 at 10:02 PM John D. Ament <jo...@apache.org> wrote:
>> Ok, I've readded some of the Weld3 support, 3 tests are failing.
>>
>> Some interesting notes:
>>
>> - If I remove Provider support, it generally works. However, I suddenly get duplicate beans of type Provider, which is confusing (but probably because of the alternative flag).
>> - I can get everything to pass in Weld, and 1 test failure in in OWB with the following:
>>
>> - Set alternative = false
>> - Remove Provider from the types
>> - Remove the filter on types to check if class.
>> - Change getId to use all of the types (makes a better toString)
>>
>>
>> If we can figure out the alternative issue with OWB, we'll be good to go again.
>>
>> John
>>
>>> On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org> wrote:
>>> I can get to some of it.
>>>
>>> We have a couple of issues now though:
>>>
>>> https://issues.jboss.org/browse/WELD-2411
>>> https://issues.jboss.org/browse/CDI-712
>>>
>>> Martin doesn't feel the spec allows you to override Provider impl's. Please feel free to weigh in :-)
>>>
>>> John
>>>
>>>
>>>> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>>>> Oh I see what you mean.
>>>> Do you mind to re-apply your fix or should I?
>>>>
>>>> Btw, I also tested with the -PWeld3 but I was not able to resolve arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>>>> We might need to add a <repository> for it in the Weld3 profile.
>>>>
>>>> I also would love to add a Weld profile. I thought we have this already but seems we missed it?
>>>>
>>>> txs and LieGrue,
>>>> strub
>>>>
>>>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>>>> >
>>>> > One note - hardcoding "isAlternative" to true breaks in Weld. Unless there is a base bean of same type, the alternative is ignored. Hence why I only did isAlternative on the provider type, all others are just regular beans.
>>>> >
>>>> > John
>>>> >
>>>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>>>> > 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<T>
>>>> > + * 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>
>>>> >
>>>> >
>>>>
>>>>
Re: 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/
Posted by "John D. Ament" <jo...@apache.org>.
Ok, I got tests passing on all three. It actually looks like its simpler
(and more correct) to not use a custom provider. The provider approach
wasn't supporting default values. I've committed changes, please take a
look and hopefully we can plan to reroll 1.0.
John
On Tue, Aug 8, 2017 at 10:02 PM John D. Ament <jo...@apache.org> wrote:
> Ok, I've readded some of the Weld3 support, 3 tests are failing.
>
> Some interesting notes:
>
> - If I remove Provider support, it generally works. However, I suddenly
> get duplicate beans of type Provider, which is confusing (but probably
> because of the alternative flag).
> - I can get everything to pass in Weld, and 1 test failure in in OWB with
> the following:
>
> - Set alternative = false
> - Remove Provider from the types
> - Remove the filter on types to check if class.
> - Change getId to use all of the types (makes a better toString)
>
>
> If we can figure out the alternative issue with OWB, we'll be good to go
> again.
>
> John
>
> On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org>
> wrote:
>
>> I can get to some of it.
>>
>> We have a couple of issues now though:
>>
>> https://issues.jboss.org/browse/WELD-2411
>> https://issues.jboss.org/browse/CDI-712
>>
>> Martin doesn't feel the spec allows you to override Provider impl's.
>> Please feel free to weigh in :-)
>>
>> John
>>
>>
>> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>>
>>> Oh I see what you mean.
>>> Do you mind to re-apply your fix or should I?
>>>
>>> Btw, I also tested with the -PWeld3 but I was not able to resolve
>>> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>>> We might need to add a <repository> for it in the Weld3 profile.
>>>
>>> I also would love to add a Weld profile. I thought we have this already
>>> but seems we missed it?
>>>
>>> txs and LieGrue,
>>> strub
>>>
>>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>>> >
>>> > One note - hardcoding "isAlternative" to true breaks in Weld. Unless
>>> there is a base bean of same type, the alternative is ignored. Hence why I
>>> only did isAlternative on the provider type, all others are just regular
>>> beans.
>>> >
>>> > John
>>> >
>>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>>> > 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<T>
>>> > + * 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>
>>> >
>>> >
>>>
>>>
>>>
Re: 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/
Posted by "John D. Ament" <jo...@apache.org>.
Ok, I've readded some of the Weld3 support, 3 tests are failing.
Some interesting notes:
- If I remove Provider support, it generally works. However, I suddenly
get duplicate beans of type Provider, which is confusing (but probably
because of the alternative flag).
- I can get everything to pass in Weld, and 1 test failure in in OWB with
the following:
- Set alternative = false
- Remove Provider from the types
- Remove the filter on types to check if class.
- Change getId to use all of the types (makes a better toString)
If we can figure out the alternative issue with OWB, we'll be good to go
again.
John
On Tue, Aug 8, 2017 at 8:44 AM John D. Ament <jo...@apache.org> wrote:
> I can get to some of it.
>
> We have a couple of issues now though:
>
> https://issues.jboss.org/browse/WELD-2411
> https://issues.jboss.org/browse/CDI-712
>
> Martin doesn't feel the spec allows you to override Provider impl's.
> Please feel free to weigh in :-)
>
> John
>
>
> On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
>
>> Oh I see what you mean.
>> Do you mind to re-apply your fix or should I?
>>
>> Btw, I also tested with the -PWeld3 but I was not able to resolve
>> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
>> We might need to add a <repository> for it in the Weld3 profile.
>>
>> I also would love to add a Weld profile. I thought we have this already
>> but seems we missed it?
>>
>> txs and LieGrue,
>> strub
>>
>> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>> >
>> > One note - hardcoding "isAlternative" to true breaks in Weld. Unless
>> there is a base bean of same type, the alternative is ignored. Hence why I
>> only did isAlternative on the provider type, all others are just regular
>> beans.
>> >
>> > John
>> >
>> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
>> > 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<T>
>> > + * 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>
>> >
>> >
>>
>>
>>
Re: 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/
Posted by "John D. Ament" <jo...@apache.org>.
I can get to some of it.
We have a couple of issues now though:
https://issues.jboss.org/browse/WELD-2411
https://issues.jboss.org/browse/CDI-712
Martin doesn't feel the spec allows you to override Provider impl's.
Please feel free to weigh in :-)
John
On Tue, Aug 8, 2017 at 7:33 AM Mark Struberg <st...@yahoo.de> wrote:
> Oh I see what you mean.
> Do you mind to re-apply your fix or should I?
>
> Btw, I also tested with the -PWeld3 but I was not able to resolve
> arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
> We might need to add a <repository> for it in the Weld3 profile.
>
> I also would love to add a Weld profile. I thought we have this already
> but seems we missed it?
>
> txs and LieGrue,
> strub
>
> > Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
> >
> > One note - hardcoding "isAlternative" to true breaks in Weld. Unless
> there is a base bean of same type, the alternative is ignored. Hence why I
> only did isAlternative on the provider type, all others are just regular
> beans.
> >
> > John
> >
> > On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
> > 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<T>
> > + * 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>
> >
> >
>
>
>
Re: 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/
Posted by Mark Struberg <st...@yahoo.de>.
Oh I see what you mean.
Do you mind to re-apply your fix or should I?
Btw, I also tested with the -PWeld3 but I was not able to resolve arquillian-weld-embedded:jar:2.0.0-SNAPSHOT
We might need to add a <repository> for it in the Weld3 profile.
I also would love to add a Weld profile. I thought we have this already but seems we missed it?
txs and LieGrue,
strub
> Am 08.08.2017 um 12:58 schrieb John D. Ament <jo...@apache.org>:
>
> One note - hardcoding "isAlternative" to true breaks in Weld. Unless there is a base bean of same type, the alternative is ignored. Hence why I only did isAlternative on the provider type, all others are just regular beans.
>
> John
>
> On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
> 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<T>
> + * 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>
>
>
Re: 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/
Posted by "John D. Ament" <jo...@apache.org>.
One note - hardcoding "isAlternative" to true breaks in Weld. Unless there
is a base bean of same type, the alternative is ignored. Hence why I only
did isAlternative on the provider type, all others are just regular beans.
John
On Tue, Aug 8, 2017 at 6:55 AM <st...@apache.org> wrote:
> 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<T>
> + * 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>
>
>
>