You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jo...@apache.org on 2017/12/24 01:56:34 UTC
svn commit: r1819195 - in /geronimo/components/config/trunk/impl/src:
main/java/org/apache/geronimo/config/
main/java/org/apache/geronimo/config/cdi/
main/java/org/apache/geronimo/config/converters/
test/java/org/apache/geronimo/config/test/internal/
Author: johndament
Date: Sun Dec 24 01:56:34 2017
New Revision: 1819195
URL: http://svn.apache.org/viewvc?rev=1819195&view=rev
Log:
GERONIMO-6597 Implementing array, list, set conversion logic. Support for class as a built in converter.
Added:
geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java
geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java
Modified:
geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java
Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java?rev=1819195&r1=1819194&r2=1819195&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java (original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java Sun Dec 24 01:56:34 2017
@@ -16,6 +16,7 @@
*/
package org.apache.geronimo.config;
+import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
@@ -36,9 +37,11 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.geronimo.config.converters.BooleanConverter;
+import org.apache.geronimo.config.converters.ClassConverter;
import org.apache.geronimo.config.converters.DoubleConverter;
import org.apache.geronimo.config.converters.DurationConverter;
import org.apache.geronimo.config.converters.FloatConverter;
@@ -70,10 +73,10 @@ import javax.enterprise.inject.Vetoed;
public class ConfigImpl implements Config {
protected Logger logger = Logger.getLogger(ConfigImpl.class.getName());
- protected List<ConfigSource> configSources = new ArrayList<>();
- protected Map<Type, Converter> converters = new HashMap<>();
- protected Map<Type, Converter> implicitConverters = new ConcurrentHashMap<>();
-
+ protected final List<ConfigSource> configSources = new ArrayList<>();
+ protected final Map<Type, Converter> converters = new HashMap<>();
+ protected final Map<Type, Converter> implicitConverters = new ConcurrentHashMap<>();
+ private static final String ARRAY_SEPARATOR_REGEX = "(?<!\\\\)" + Pattern.quote(",");
public ConfigImpl() {
registerDefaultConverter();
@@ -101,6 +104,7 @@ public class ConfigImpl implements Confi
converters.put(Instant.class, InstantConverter.INSTANCE);
converters.put(URL.class, URLConverter.INSTANCE);
+ converters.put(Class.class, ClassConverter.INSTANCE);
}
@@ -143,13 +147,37 @@ public class ConfigImpl implements Confi
public <T> T convert(String value, Class<T> asType) {
if (value != null) {
- Converter<T> converter = getConverter(asType);
- return converter.convert(value);
+ if(asType.isArray()) {
+ Class<?> elementType = asType.getComponentType();
+ List<?> elements = convertList(value, elementType);
+ Object arrayInst = Array.newInstance(elementType, elements.size());
+ for (int i = 0; i < elements.size(); i++) {
+ Array.set(arrayInst, i, elements.get(i));
+ }
+ return (T) arrayInst;
+ } else {
+ Converter<T> converter = getConverter(asType);
+ return converter.convert(value);
+ }
}
-
return null;
}
+ public <T> List<T> convertList(String rawValue, Class<T> arrayElementType) {
+ Converter<T> converter = getConverter(arrayElementType);
+ String[] parts = rawValue.split(ARRAY_SEPARATOR_REGEX);
+ if(parts.length == 0) {
+ return Collections.emptyList();
+ }
+ List<T> elements = new ArrayList<>(parts.length);
+ for (String part : parts) {
+ part = part.replace("\\,", ",");
+ T converted = converter.convert(part);
+ elements.add(converted);
+ }
+ return elements;
+ }
+
private <T> Converter getConverter(Class<T> asType) {
Converter converter = converters.get(asType);
if (converter == null) {
@@ -197,7 +225,10 @@ public class ConfigImpl implements Confi
allConfigSources.addAll(configSourcesToAdd);
// finally put all the configSources back into the map
- configSources = sortDescending(allConfigSources);
+ synchronized (configSources) {
+ configSources.clear();
+ configSources.addAll(sortDescending(allConfigSources));
+ }
}
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=1819195&r1=1819194&r2=1819195&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 Sun Dec 24 01:56:34 2017
@@ -37,6 +37,8 @@ import java.lang.reflect.ParameterizedTy
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
@@ -111,22 +113,42 @@ public class ConfigInjectionBean<T> impl
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 getConfigValue(key, defaultValue, 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);
- }
-
- if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Supplier.class) && paramType.getActualTypeArguments().length == 1) {
- Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
- return (T) new ConfigSupplier(clazz, key, defaultValue, (ConfigImpl)getConfig());
+ if(rawType instanceof Class && paramType.getActualTypeArguments().length == 1) {
+ // handle Provider<T>
+ Class<?> rawTypeClass = ((Class<?>) rawType);
+ if (rawTypeClass.isAssignableFrom(Provider.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return getConfigValue(key, defaultValue, clazz);
+ }
+
+ // handle Optional<T>
+ if (rawTypeClass.isAssignableFrom(Optional.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return (T) getConfig().getOptionalValue(key, clazz);
+ }
+
+ if (rawTypeClass.isAssignableFrom(Supplier.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ return (T) new ConfigSupplier(clazz, key, defaultValue, (ConfigImpl)getConfig());
+ }
+
+ if (rawTypeClass.isAssignableFrom(Set.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+
+ // read the array type, convert it to a Set
+ ConfigImpl config = (ConfigImpl) getConfig();
+ String value = config.getValue(key);
+ List<Object> elements = config.convertList(value, clazz);
+ return (T)new LinkedHashSet<>(elements);
+ }
+
+ if (rawTypeClass.isAssignableFrom(List.class)) {
+ Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc
+ // read the array type, convert it to a List
+ ConfigImpl config = (ConfigImpl) getConfig();
+ String value = config.getValue(key);
+ return (T)config.convertList(value, clazz);
+ }
}
}
else {
Added: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java?rev=1819195&view=auto
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java (added)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java Sun Dec 24 01:56:34 2017
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.geronimo.config.converters;
+
+import org.eclipse.microprofile.config.spi.Converter;
+
+import javax.annotation.Priority;
+import javax.enterprise.inject.Vetoed;
+
+@Priority(1)
+@Vetoed
+public class ClassConverter implements Converter<Class>{
+ public static final Converter<Class> INSTANCE = new ClassConverter();
+ @Override
+ public Class convert(String value) {
+ if(value == null) {
+ return null;
+ }
+ try {
+ return Class.forName(value);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
Added: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java?rev=1819195&view=auto
==============================================================================
--- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java (added)
+++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java Sun Dec 24 01:56:34 2017
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.config.test.internal;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+public class ArrayTypeTest extends Arquillian {
+ private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
+ private static final String SOME_OTHER_KEY = "org.apache.geronimo.config.test.internal.someotherkey";
+
+ @Deployment
+ public static WebArchive deploy() {
+ System.setProperty(SOME_KEY, "1,2,3");
+ System.setProperty(SOME_OTHER_KEY, "1,2\\,3");
+ JavaArchive testJar = ShrinkWrap
+ .create(JavaArchive.class, "arrayTest.jar")
+ .addClasses(ArrayTypeTest.class, SomeBean.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return ShrinkWrap
+ .create(WebArchive.class, "arrayTest.war")
+ .addAsLibrary(testJar);
+ }
+
+ @Inject
+ private SomeBean someBean;
+
+ @Test
+ public void testArraySetListInjection() {
+ Assert.assertEquals(someBean.getStringValue(), "1,2,3");
+ Assert.assertEquals(someBean.getMyconfig(), new int[]{1,2,3});
+ Assert.assertEquals(someBean.getIntValues(), asList(1,2,3));
+ Assert.assertEquals(someBean.getIntSet(), new LinkedHashSet<>(asList(1,2,3)));
+ }
+
+ @Test
+ public void testListWithEscaping() {
+ Assert.assertEquals(someBean.getValues(), asList("1","2,3"));
+ }
+
+ @RequestScoped
+ public static class SomeBean {
+
+ @Inject
+ @ConfigProperty(name=SOME_KEY)
+ private int[] myconfig;
+
+ @Inject
+ @ConfigProperty(name=SOME_KEY)
+ private List<Integer> intValues;
+
+ @Inject
+ @ConfigProperty(name=SOME_KEY)
+ private Set<Integer> intSet;
+
+ @Inject
+ @ConfigProperty(name=SOME_KEY)
+ private String stringValue;
+
+ @Inject
+ @ConfigProperty(name=SOME_OTHER_KEY)
+ private List<String> values;
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ public int[] getMyconfig() {
+ return myconfig;
+ }
+
+ public List<Integer> getIntValues() {
+ return intValues;
+ }
+
+ public Set<Integer> getIntSet() {
+ return intSet;
+ }
+
+ public List<String> getValues() {
+ return values;
+ }
+ }
+}