You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/11/14 16:17:28 UTC
svn commit: r1815229 - in /felix/trunk/osgi-r7/configurator: ./
src/main/java/org/apache/felix/configurator/impl/json/
src/test/java/org/apache/felix/configurator/impl/json/
src/test/resources/json/
Author: cziegeler
Date: Tue Nov 14 16:17:28 2017
New Revision: 1815229
URL: http://svn.apache.org/viewvc?rev=1815229&view=rev
Log:
Update to latest converter and add handling of special cases incl test case
Added:
felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json (with props)
Modified:
felix/trunk/osgi-r7/configurator/pom.xml
felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java
felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/TypeConverter.java
felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/json/TypeConverterTest.java
Modified: felix/trunk/osgi-r7/configurator/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/pom.xml?rev=1815229&r1=1815228&r2=1815229&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/pom.xml (original)
+++ felix/trunk/osgi-r7/configurator/pom.xml Tue Nov 14 16:17:28 2017
@@ -101,7 +101,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.converter</artifactId>
- <version>0.1.0-SNAPSHOT</version>
+ <version>0.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
Modified: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java?rev=1815229&r1=1815228&r2=1815229&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java (original)
+++ felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java Tue Nov 14 16:17:28 2017
@@ -239,17 +239,8 @@ public class JSONUtil {
}
} else {
try {
- Object convertedVal = converter.convert(pid, value, typeInfo);
- if ( convertedVal == null ) {
- JsonStructure json = build(value);
- if ( json == null ) {
- convertedVal = value.toString();
- } else {
- final StringWriter writer = new StringWriter();
- Json.createWriter(writer).write(json);
- convertedVal = writer.toString();
- }
- }
+
+ final Object convertedVal = getTypedValue(converter, pid, value, typeInfo);
properties.put(key, convertedVal);
} catch ( final IOException io ) {
report.errors.add("Invalid value/type for configuration in '" + identifier + "' : " + pid + " - " + mapKey + " : " + io.getMessage());
@@ -269,7 +260,7 @@ public class JSONUtil {
return configurations;
}
- private static JsonStructure build(final Object value) {
+ public static JsonStructure build(final Object value) {
if ( value instanceof List ) {
@SuppressWarnings("unchecked")
final List<Object> list = (List<Object>)value;
@@ -398,6 +389,36 @@ public class JSONUtil {
return null;
}
+ public static Object getTypedValue(final TypeConverter converter,
+ final String pid,
+ final Object value,
+ final String typeInfo) throws IOException {
+ Object convertedVal = converter.convert(pid, value, typeInfo);
+ if ( convertedVal == null ) {
+ if ( typeInfo != null ) {
+ throw new IOException("Unable to convert to type " + typeInfo);
+ }
+ JsonStructure json = build(value);
+ if ( json == null ) {
+ convertedVal = value.toString();
+ } else {
+ // JSON Structure, this will result in a String or in an array of Strings
+ if ( json.getValueType() == ValueType.ARRAY ) {
+ final JsonArray arr = (JsonArray)json;
+ final String[] val = new String[arr.size()];
+ for(int i=0;i<val.length;i++) {
+ val[i] = TypeConverter.getConverter().convert(arr.get(i)).to(String.class);
+ }
+ convertedVal = val;
+
+ } else {
+ convertedVal = TypeConverter.getConverter().convert(value).to(String.class);
+ }
+ }
+ }
+ return convertedVal;
+ }
+
/**
* Verify the JSON according to the rules
* @param name The JSON name
Modified: felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/TypeConverter.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/TypeConverter.java?rev=1815229&r1=1815228&r2=1815229&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/TypeConverter.java (original)
+++ felix/trunk/osgi-r7/configurator/src/main/java/org/apache/felix/configurator/impl/json/TypeConverter.java Tue Nov 14 16:17:28 2017
@@ -20,17 +20,90 @@ package org.apache.felix.configurator.im
import java.io.File;
import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.reflect.Type;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonStructure;
import org.osgi.util.converter.Converter;
+import org.osgi.util.converter.ConverterFunction;
import org.osgi.util.converter.Converters;
+import org.osgi.util.converter.TargetRule;
import org.osgi.util.converter.TypeReference;
public class TypeConverter {
public static Converter getConverter() {
- return Converters.standardConverter();
+ return Converters.standardConverter().newConverterBuilder().rule(new TargetRule() {
+
+ @Override
+ public Type getTargetType() {
+ return String.class;
+ }
+
+ @Override
+ public ConverterFunction getFunction() {
+ return new ConverterFunction() {
+
+ @Override
+ public Object apply(final Object obj, final Type targetType) throws Exception {
+ if ( obj instanceof Map || obj instanceof List ) {
+ final JsonStructure json = JSONUtil.build(obj);
+ final StringWriter w = new StringWriter();
+ Json.createWriter(w).write(json);
+ return w.toString();
+ }
+ return CANNOT_HANDLE;
+ }
+ };
+ }
+ }).build();
+ }
+
+ private static final Map<String, Class<?>> TYPE_MAP = new HashMap<>();
+ static {
+ // scalar types and primitive types
+ TYPE_MAP.put("String", String.class);
+ TYPE_MAP.put("Integer", Integer.class);
+ TYPE_MAP.put("int", Integer.class);
+ TYPE_MAP.put("Long", Long.class);
+ TYPE_MAP.put("long", Long.class);
+ TYPE_MAP.put("Float", Float.class);
+ TYPE_MAP.put("float", Float.class);
+ TYPE_MAP.put("Double", Double.class);
+ TYPE_MAP.put("double", Double.class);
+ TYPE_MAP.put("Byte", Byte.class);
+ TYPE_MAP.put("byte", Byte.class);
+ TYPE_MAP.put("Short", Short.class);
+ TYPE_MAP.put("short", Short.class);
+ TYPE_MAP.put("Character", Character.class);
+ TYPE_MAP.put("char", Character.class);
+ TYPE_MAP.put("Boolean", Boolean.class);
+ TYPE_MAP.put("boolean", Boolean.class);
+ // array of scalar types and primitive types
+ TYPE_MAP.put("String[]", String[].class);
+ TYPE_MAP.put("Integer[]", Integer[].class);
+ TYPE_MAP.put("int[]", int[].class);
+ TYPE_MAP.put("Long[]", Long[].class);
+ TYPE_MAP.put("long[]", long[].class);
+ TYPE_MAP.put("Float[]", Float[].class);
+ TYPE_MAP.put("float[]", float[].class);
+ TYPE_MAP.put("Double[]", Double[].class);
+ TYPE_MAP.put("double[]", double[].class);
+ TYPE_MAP.put("Byte[]", Byte[].class);
+ TYPE_MAP.put("byte[]", byte[].class);
+ TYPE_MAP.put("Short[]", Short[].class);
+ TYPE_MAP.put("short[]", short[].class);
+ TYPE_MAP.put("Boolean[]", Boolean[].class);
+ TYPE_MAP.put("boolean[]", boolean[].class);
+ TYPE_MAP.put("Character[]", Character[].class);
+ TYPE_MAP.put("char[]", char[].class);
}
private final List<File> allFiles = new ArrayList<>();
@@ -79,15 +152,19 @@ public class TypeConverter {
return new String[0];
}
final Object firstObject = list.get(0);
- if ( firstObject instanceof String ) {
- return getConverter().convert(list).defaultValue(null).to(String[].class);
- } else if ( firstObject instanceof Boolean ) {
- return getConverter().convert(list).defaultValue(null).to(Boolean[].class);
- } else if ( firstObject instanceof Long || firstObject instanceof Integer ) {
- return getConverter().convert(list).defaultValue(null).to(Long[].class);
+ Object convertedValue = null;
+ if ( firstObject instanceof Boolean ) {
+ convertedValue = getConverter().convert(list).defaultValue(null).to(Boolean[].class);
+ } else if ( firstObject instanceof Long || firstObject instanceof Integer || firstObject instanceof Byte || firstObject instanceof Short ) {
+ convertedValue = getConverter().convert(list).defaultValue(null).to(Long[].class);
} else if ( firstObject instanceof Double || firstObject instanceof Float ) {
- return getConverter().convert(list).defaultValue(null).to(Double[].class);
+ convertedValue = getConverter().convert(list).defaultValue(null).to(Double[].class);
+ }
+ if ( convertedValue == null ) {
+ // convert to String (TODO)
+ convertedValue = getConverter().convert(list).defaultValue(null).to(String[].class);
}
+ return convertedValue;
}
return null;
}
@@ -148,87 +225,9 @@ public class TypeConverter {
return filePaths;
}
- // scalar types and primitive types
- if ( "String".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(String.class);
-
- } else if ( "Integer".equals(typeInfo) || "int".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Integer.class);
-
- } else if ( "Long".equals(typeInfo) || "long".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Long.class);
-
- } else if ( "Float".equals(typeInfo) || "float".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Float.class);
-
- } else if ( "Double".equals(typeInfo) || "double".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Double.class);
-
- } else if ( "Byte".equals(typeInfo) || "byte".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Byte.class);
-
- } else if ( "Short".equals(typeInfo) || "short".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Short.class);
-
- } else if ( "Character".equals(typeInfo) || "char".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Character.class);
-
- } else if ( "Boolean".equals(typeInfo) || "boolean".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Boolean.class);
-
- }
-
- // array of scalar types and primitive types
- if ( "String[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(String[].class);
-
- } else if ( "Integer[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Integer[].class);
-
- } else if ( "int[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(int[].class);
-
- } else if ( "Long[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Long[].class);
-
- } else if ( "long[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(long[].class);
-
- } else if ( "Float[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Float[].class);
-
- } else if ( "float[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(float[].class);
-
- } else if ( "Double[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Double[].class);
-
- } else if ( "double[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(double[].class);
-
- } else if ( "Byte[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Byte[].class);
-
- } else if ( "byte[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(byte[].class);
-
- } else if ( "Short[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Short[].class);
-
- } else if ( "short[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(short[].class);
-
- } else if ( "Character[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Character[].class);
-
- } else if ( "char[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(char[].class);
-
- } else if ( "Boolean[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(Boolean[].class);
-
- } else if ( "boolean[]".equals(typeInfo) ) {
- return getConverter().convert(value).defaultValue(null).to(boolean[].class);
+ final Class<?> typeClass = TYPE_MAP.get(typeInfo);
+ if ( typeClass != null ) {
+ return getConverter().convert(value).defaultValue(null).to(typeClass);
}
// Collections of scalar types
@@ -258,6 +257,30 @@ public class TypeConverter {
} else if ( "Collection<Boolean>".equals(typeInfo) ) {
return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Boolean>>() {});
+ } else if ( "Collection".equals(typeInfo) ) {
+ if ( value instanceof List ) {
+ @SuppressWarnings("unchecked")
+ final List<Object> list = (List<Object>)value;
+ if ( list.isEmpty() ) {
+ return new String[0];
+ }
+ final Object firstObject = list.get(0);
+ Object convertedValue = null;
+ if ( firstObject instanceof Boolean ) {
+ convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<List<Boolean>>() {});
+ } else if ( firstObject instanceof Long || firstObject instanceof Integer || firstObject instanceof Byte || firstObject instanceof Short) {
+ convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<List<Long>>() {});
+ } else if ( firstObject instanceof Double || firstObject instanceof Float ) {
+ convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<List<Double>>() {});
+ }
+ if ( convertedValue == null ) {
+
+ // convert to String (TODO)
+ convertedValue = getConverter().convert(list).defaultValue(null).to(new TypeReference<List<String>>() {});
+ }
+ return convertedValue;
+ }
+ return getConverter().convert(value).defaultValue(null).to(Collection.class);
}
// unknown type - ignore configuration
Modified: felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/json/TypeConverterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/json/TypeConverterTest.java?rev=1815229&r1=1815228&r2=1815229&view=diff
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/json/TypeConverterTest.java (original)
+++ felix/trunk/osgi-r7/configurator/src/test/java/org/apache/felix/configurator/impl/json/TypeConverterTest.java Tue Nov 14 16:17:28 2017
@@ -19,6 +19,7 @@
package org.apache.felix.configurator.impl.json;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -26,11 +27,10 @@ import static org.junit.Assert.assertTru
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Collection;
+import java.util.Iterator;
import javax.json.JsonObject;
-import org.apache.felix.configurator.impl.json.JSONUtil;
-import org.apache.felix.configurator.impl.json.TypeConverter;
import org.junit.Test;
public class TypeConverterTest {
@@ -250,4 +250,75 @@ public class TypeConverterTest {
assertTrue(converter.convert(null, JSONUtil.getValue(properties, "boolean.array"), "Collection<Boolean>") instanceof Collection<?>);
assertTrue(((Collection<Boolean>)converter.convert(null, JSONUtil.getValue(properties, "boolean.array"), "Collection<Boolean>")).iterator().next() instanceof Boolean);
}
+
+ private Object getConverted(final String propName, final String typeInfo) throws Exception {
+ final TypeConverter converter = new TypeConverter(null);
+ final JsonObject config = JSONUtil.parseJSON("a",
+ JSONUtilTest.readJSON("json/complex-types.json"),
+ new JSONUtil.Report());
+ final JsonObject properties = (JsonObject)config.get("config");
+
+ final Object value = JSONUtil.getValue(properties, propName);
+ assertNotNull(value);
+ final Object converted = JSONUtil.getTypedValue(converter, null, value, typeInfo);
+ assertNotNull(converted);
+
+ return converted;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test public void testUntypedLongCollection() throws Exception {
+ final Object converted = getConverted("untyped", "Collection");
+ assertTrue(converted instanceof Collection<?>);
+ final Iterator<Object> iter = ((Collection<Object>)converted).iterator();
+ assertEquals(1L, iter.next());
+ assertEquals(2L, iter.next());
+ assertEquals(3L, iter.next());
+ assertFalse(iter.hasNext());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test public void testUntypedMixedCollection() throws Exception {
+ // an untyped collection is tried to be converted to the type
+ // of the first item in the list. If that fails, String is used.
+ final Object converted = getConverted("untyped_mixed", "Collection");
+ assertTrue(converted instanceof Collection<?>);
+ final Iterator<Object> iter = ((Collection<Object>)converted).iterator();
+ assertEquals("1", iter.next());
+ assertEquals("two", iter.next());
+ assertEquals("3", iter.next());
+ assertFalse(iter.hasNext());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test public void testEmptyTypedCollection() throws Exception {
+ final Object converted = getConverted("empty", "Collection<Integer>");
+ assertTrue(converted instanceof Collection<?>);
+ final Iterator<Object> iter = ((Collection<Object>)converted).iterator();
+ assertFalse(iter.hasNext());
+ }
+
+ @Test public void testObjectArray() throws Exception {
+ final Object converted = getConverted("objects_array", null);
+ assertTrue(converted.getClass().isArray());
+ final String[] vals = (String[])converted;
+ assertEquals(2, vals.length);
+ assertTrue(vals[0] instanceof String);
+ assertTrue(vals[1] instanceof String);
+ assertEquals("{\"foo\":1}", vals[0]);
+ assertEquals("{\"foo\":2}", vals[1]);
+ }
+
+ @Test public void testMixedObjectArray() throws Exception {
+ final Object converted = getConverted("objects_array_mixed", null);
+ assertTrue(converted.getClass().isArray());
+ final String[] vals = (String[])converted;
+ assertEquals(3, vals.length);
+ assertTrue(vals[0] instanceof String);
+ assertTrue(vals[1] instanceof String);
+ assertTrue(vals[2] instanceof String);
+ assertEquals("2", vals[0]);
+ assertEquals("{\"foo\":1}", vals[1]);
+ assertEquals("{\"foo\":2}", vals[2]);
+ }
}
Added: felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json?rev=1815229&view=auto
==============================================================================
--- felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json (added)
+++ felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json Tue Nov 14 16:17:28 2017
@@ -0,0 +1,16 @@
+{
+ "config" : {
+ "untyped" : [1,2,3],
+ "untyped_mixed" : [1,"two",3],
+ "empty" : [],
+ "objects_array" : [
+ {"foo":1},
+ {"foo":2}
+ ],
+ "objects_array_mixed" : [
+ 2,
+ {"foo":1},
+ {"foo":2}
+ ]
+ }
+}
Propchange: felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/osgi-r7/configurator/src/test/resources/json/complex-types.json
------------------------------------------------------------------------------
svn:keywords = Id