diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializer.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializer.java index 3f314633a5..5adee692f3 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializer.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializer.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.eclipse.che.api.core.model.workspace.devfile.Component; @@ -50,6 +51,36 @@ public class PreferencesDeserializer extends JsonDeserializer array = new ArrayList<>(); + // Iterate over nested array + JsonToken nextValue = jsonParser.nextValue(); + while (!JsonToken.END_ARRAY.equals(nextValue)) { + + switch (nextValue) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + array.add(jsonParser.getNumberValue()); + break; + case VALUE_FALSE: + case VALUE_TRUE: + array.add(jsonParser.getValueAsBoolean()); + break; + case VALUE_STRING: + array.add(jsonParser.getValueAsString()); + break; + default: + throw new JsonParseException( + jsonParser, + format( + "Unexpected value in the nested array of the preference with key '%s'.", + key)); + } + nextValue = jsonParser.nextValue(); + } + result.put(key, array.toArray()); + break; default: throw new JsonParseException( jsonParser, diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverter.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverter.java index 1cb441de7a..2bea7aabf6 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverter.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverter.java @@ -12,9 +12,12 @@ package org.eclipse.che.api.workspace.server.devfile; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import javax.persistence.AttributeConverter; import javax.persistence.Converter; import org.eclipse.che.api.core.model.workspace.devfile.Component; @@ -47,9 +50,30 @@ public class SerializableConverter implements AttributeConverter values = new ArrayList<>(); + node.elements().forEachRemaining(n -> values.add(serializableNodeValue(n))); + return values.toArray(); + } else { + throw new RuntimeException("Unable to deserialize preference value:" + dbData); + } } catch (IOException e) { throw new RuntimeException("Unable to deserialize preference value:" + e.getMessage(), e); } } + + private Serializable serializableNodeValue(JsonNode node) { + if (node.isNumber()) { + return node.numberValue(); + } else if (node.isBoolean()) { + return node.booleanValue(); + } else if (node.isTextual()) { + return node.textValue(); + } else { + throw new RuntimeException("Unable to deserialize preference value:" + node.asText()); + } + } } diff --git a/wsmaster/che-core-api-workspace/src/main/resources/schema/1.0.0/devfile.json b/wsmaster/che-core-api-workspace/src/main/resources/schema/1.0.0/devfile.json index 8257c10525..8dac07a20f 100644 --- a/wsmaster/che-core-api-workspace/src/main/resources/schema/1.0.0/devfile.json +++ b/wsmaster/che-core-api-workspace/src/main/resources/schema/1.0.0/devfile.json @@ -347,10 +347,24 @@ "{\"java.home\": \"/home/user/jdk11\", \"java.jdt.ls.vmargs\": \"-Xmx1G\"}" ], "additionalProperties": { - "type": [ - "boolean", - "string", - "number" + "anyOf" : [ + { + "type": [ + "boolean", + "string", + "number" + ] + }, + { + "type": "array", + "items": { + "type": [ + "boolean", + "string", + "number" + ] + } + } ] } } diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializerTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializerTest.java index 0e6c3eb9f3..66b950858a 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializerTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/PreferencesDeserializerTest.java @@ -12,7 +12,6 @@ package org.eclipse.che.api.workspace.server.devfile; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; @@ -42,16 +41,22 @@ public class PreferencesDeserializerTest { + "\"valid.string\": \"/usr/bin/value\"," + "\"valid.boolean\": false," + "\"valid.integer\": 777555888," - + "\"valid.float\": 3.1415926" + + "\"valid.float\": 3.1415926," + + "\"valid.string.array\": [\"foo\",\"bar\",\"baz\"]," + + "\"valid.int.array\": [12,13,0]," + + "\"valid.bool.array\": [true,false,false]" + "}"; final JsonParser parser = factory.createParser(json); Map result = preferencesDeserializer.deserialize(parser, ctxt); - assertEquals(4, result.size()); - assertTrue(result.containsValue(777555888)); - assertTrue(result.containsValue(3.1415926)); - assertTrue(result.containsValue(false)); - assertTrue(result.containsValue("/usr/bin/value")); + assertEquals(7, result.size()); + assertEquals(result.get("valid.integer"), 777555888); + assertEquals(result.get("valid.float"), 3.1415926); + assertEquals(result.get("valid.boolean"), false); + assertEquals(result.get("valid.string"), "/usr/bin/value"); + assertEquals(result.get("valid.string.array"), new String[] {"foo", "bar", "baz"}); + assertEquals(result.get("valid.int.array"), new int[] {12, 13, 0}); + assertEquals(result.get("valid.bool.array"), new boolean[] {true, false, false}); } @Test( diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverterTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverterTest.java new file mode 100644 index 0000000000..6d8339518c --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/SerializableConverterTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server.devfile; + +import static org.testng.Assert.assertEquals; + +import java.io.Serializable; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class SerializableConverterTest { + + private final SerializableConverter converter = new SerializableConverter(); + + @DataProvider + public static Object[][] SerializableProvider() { + return new Object[][] { + {"foo"}, + {"bar"}, + {true}, + {false}, + {Integer.MAX_VALUE}, + {0}, + {Integer.MIN_VALUE}, + {"{\"java.home\": \"/home/user/jdk11\", \"java.jdt.ls.vmargs\": \"-Xmx1G\"}"}, + {new String[] {"single"}}, + {new String[] {"--enable-all", "--new"}}, + {new int[] {213, 456, 459}}, + {new boolean[] {true, false, false}} + }; + } + + @Test(dataProvider = "SerializableProvider") + public void testConvertToDatabaseColumnAndBack(Serializable initialObj) { + String res = converter.convertToDatabaseColumn(initialObj); + Serializable backObj = converter.convertToEntityAttribute(res); + assertEquals(initialObj, backObj); + } +} diff --git a/wsmaster/che-core-api-workspace/src/test/resources/devfile/schema_test/editor_plugin_component/devfile_plugin_components_with_preferences.yaml b/wsmaster/che-core-api-workspace/src/test/resources/devfile/schema_test/editor_plugin_component/devfile_plugin_components_with_preferences.yaml index 2d666a015d..cfa5f8af94 100644 --- a/wsmaster/che-core-api-workspace/src/test/resources/devfile/schema_test/editor_plugin_component/devfile_plugin_components_with_preferences.yaml +++ b/wsmaster/che-core-api-workspace/src/test/resources/devfile/schema_test/editor_plugin_component/devfile_plugin_components_with_preferences.yaml @@ -20,3 +20,4 @@ components: java.home: '/home/user/jdk11' java.jdt.ls.vmargs: '-noverify -Xmx1G -XX:+UseG1GC -XX:+UseStringDeduplication' java.jtg.memory: 12345 + go.lintFlags: ["--enable-all", "--new"]