From 185ba21b238f3ed9e28e1c46ba4f57a5a2e6ebdb Mon Sep 17 00:00:00 2001 From: Kartoffelsup Date: Tue, 15 Nov 2016 08:49:22 +0100 Subject: [PATCH] Replace org.json with json-simple in configuration-metadata gh-5929 --- .../pom.xml | 5 +- ...gurationMetadataRepositoryJsonBuilder.java | 9 +- .../configurationmetadata/JsonReader.java | 160 +++++++++--------- .../JsonReaderTests.java | 22 ++- 4 files changed, 100 insertions(+), 96 deletions(-) diff --git a/spring-boot-tools/spring-boot-configuration-metadata/pom.xml b/spring-boot-tools/spring-boot-configuration-metadata/pom.xml index 6374a429cd40..f54557497916 100644 --- a/spring-boot-tools/spring-boot-configuration-metadata/pom.xml +++ b/spring-boot-tools/spring-boot-configuration-metadata/pom.xml @@ -18,10 +18,9 @@ ${basedir}/../.. - - org.json - json + com.googlecode.json-simple + json-simple diff --git a/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilder.java b/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilder.java index f268a26dccbf..94f6f2905c79 100644 --- a/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilder.java +++ b/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilder.java @@ -16,6 +16,8 @@ package org.springframework.boot.configurationmetadata; +import org.json.simple.parser.ParseException; + import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; @@ -23,8 +25,6 @@ import java.util.List; import java.util.Map; -import org.json.JSONException; - /** * Load a {@link ConfigurationMetadataRepository} from the content of arbitrary * resource(s). @@ -98,8 +98,7 @@ public ConfigurationMetadataRepository build() { return result; } - private SimpleConfigurationMetadataRepository add(InputStream in, Charset charset) - throws IOException { + private SimpleConfigurationMetadataRepository add(InputStream in, Charset charset) { try { RawConfigurationMetadata metadata = this.reader.read(in, charset); return create(metadata); @@ -108,7 +107,7 @@ private SimpleConfigurationMetadataRepository add(InputStream in, Charset charse throw new IllegalArgumentException( "Failed to read configuration " + "metadata", ex); } - catch (JSONException ex) { + catch (ParseException ex) { throw new IllegalArgumentException( "Invalid configuration " + "metadata document", ex); } diff --git a/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/JsonReader.java b/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/JsonReader.java index 97b33969f248..6df36cbdc6d8 100644 --- a/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/JsonReader.java +++ b/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/JsonReader.java @@ -19,13 +19,18 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringWriter; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collections; import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; -import org.json.JSONArray; -import org.json.JSONObject; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; /** * Read standard json metadata format as {@link ConfigurationMetadataRepository}. @@ -40,7 +45,7 @@ class JsonReader { private final DescriptionExtractor descriptionExtractor = new DescriptionExtractor(); public RawConfigurationMetadata read(InputStream in, Charset charset) - throws IOException { + throws IOException, ParseException { JSONObject json = readJson(in, charset); List groups = parseAllSources(json); List items = parseAllItems(json); @@ -49,102 +54,83 @@ public RawConfigurationMetadata read(InputStream in, Charset charset) } private List parseAllSources(JSONObject root) { - List result = new ArrayList(); - if (!root.has("groups")) { - return result; - } - JSONArray sources = root.getJSONArray("groups"); - for (int i = 0; i < sources.length(); i++) { - JSONObject source = sources.getJSONObject(i); - result.add(parseSource(source)); - } - return result; + return parse(root, this::parseSource, "groups"); } private List parseAllItems(JSONObject root) { - List result = new ArrayList(); - if (!root.has("properties")) { - return result; - } - JSONArray items = root.getJSONArray("properties"); - for (int i = 0; i < items.length(); i++) { - JSONObject item = items.getJSONObject(i); - result.add(parseItem(item)); - } - return result; + return parse(root, this::parseItem, "properties"); } private List parseAllHints(JSONObject root) { - List result = new ArrayList(); - if (!root.has("hints")) { - return result; - } - JSONArray items = root.getJSONArray("hints"); - for (int i = 0; i < items.length(); i++) { - JSONObject item = items.getJSONObject(i); - result.add(parseHint(item)); + return parse(root, this::parseHint, "hints"); + } + + private List parse(JSONObject root, Function parser, String key) { + if (!root.containsKey(key)) { + return Collections.emptyList(); } - return result; + + List items = getMustExist(root, (key)); + return items.stream().map(parser).collect(Collectors.toList()); } private ConfigurationMetadataSource parseSource(JSONObject json) { ConfigurationMetadataSource source = new ConfigurationMetadataSource(); - source.setGroupId(json.getString("name")); - source.setType(json.optString("type", null)); - String description = json.optString("description", null); + source.setGroupId(getMustExist(json, "name")); + source.setType(getOrNull(json, "type")); + String description = getOrNull(json, "description"); source.setDescription(description); source.setShortDescription( this.descriptionExtractor.getShortDescription(description)); - source.setSourceType(json.optString("sourceType", null)); - source.setSourceMethod(json.optString("sourceMethod", null)); + source.setSourceType(getOrNull(json, "sourceType")); + source.setSourceMethod(getOrNull(json, "sourceMethod")); return source; } private ConfigurationMetadataItem parseItem(JSONObject json) { ConfigurationMetadataItem item = new ConfigurationMetadataItem(); - item.setId(json.getString("name")); - item.setType(json.optString("type", null)); - String description = json.optString("description", null); + item.setId(getMustExist(json, "name")); + item.setType(getOrNull(json, "type")); + String description = getOrNull(json, "description"); item.setDescription(description); item.setShortDescription( this.descriptionExtractor.getShortDescription(description)); - item.setDefaultValue(readItemValue(json.opt("defaultValue"))); + item.setDefaultValue(readItemValue(getOrNull(json, "defaultValue"))); item.setDeprecation(parseDeprecation(json)); - item.setSourceType(json.optString("sourceType", null)); - item.setSourceMethod(json.optString("sourceMethod", null)); + item.setSourceType(getOrNull(json, "sourceType")); + item.setSourceMethod(getOrNull(json, "sourceMethod")); return item; } private ConfigurationMetadataHint parseHint(JSONObject json) { ConfigurationMetadataHint hint = new ConfigurationMetadataHint(); - hint.setId(json.getString("name")); - if (json.has("values")) { - JSONArray values = json.getJSONArray("values"); - for (int i = 0; i < values.length(); i++) { - JSONObject value = values.getJSONObject(i); + hint.setId(getMustExist(json, ("name"))); + if (json.containsKey("values")) { + JSONArray values = getMustExist(json, "values"); + for (int i = 0; i < values.size(); i++) { + JSONObject value = (JSONObject) values.get(i); ValueHint valueHint = new ValueHint(); - valueHint.setValue(readItemValue(value.get("value"))); - String description = value.optString("description", null); + valueHint.setValue(readItemValue(getMustExist(value, "value"))); + String description = getOrNull(value, "description"); valueHint.setDescription(description); valueHint.setShortDescription( this.descriptionExtractor.getShortDescription(description)); hint.getValueHints().add(valueHint); } } - if (json.has("providers")) { - JSONArray providers = json.getJSONArray("providers"); - for (int i = 0; i < providers.length(); i++) { - JSONObject provider = providers.getJSONObject(i); + if (json.containsKey("providers")) { + JSONArray providers = getMustExist(json, ("providers")); + for (int i = 0; i < providers.size(); i++) { + JSONObject provider = (JSONObject) providers.get(i); ValueProvider valueProvider = new ValueProvider(); - valueProvider.setName(provider.getString("name")); - if (provider.has("parameters")) { - JSONObject parameters = provider.getJSONObject("parameters"); - Iterator keys = parameters.keys(); - while (keys.hasNext()) { - String key = (String) keys.next(); + valueProvider.setName(getMustExist(provider, "name")); + if (provider.containsKey("parameters")) { + JSONObject parameters = getMustExist(provider, "parameters"); + Set keys = parameters.keySet(); + keys.forEach( key -> { valueProvider.getParameters().put(key, - readItemValue(parameters.get(key))); - } + readItemValue(getMustExist(parameters, key))); + }); } hint.getValueProviders().add(valueProvider); } @@ -153,22 +139,23 @@ private ConfigurationMetadataHint parseHint(JSONObject json) { } private Deprecation parseDeprecation(JSONObject object) { - if (object.has("deprecation")) { - JSONObject deprecationJsonObject = object.getJSONObject("deprecation"); + if (object.containsKey("deprecation")) { + JSONObject deprecationJsonObject = getMustExist(object, "deprecation"); Deprecation deprecation = new Deprecation(); - deprecation.setReason(deprecationJsonObject.optString("reason", null)); + deprecation.setReason(getOrNull(deprecationJsonObject, "reason")); deprecation - .setReplacement(deprecationJsonObject.optString("replacement", null)); + .setReplacement(getOrNull(deprecationJsonObject, "replacement")); return deprecation; } - return (object.optBoolean("deprecated") ? new Deprecation() : null); + final Boolean deprecated = getOrNull(object, "deprecated"); + return (deprecated != null && deprecated) ? new Deprecation() : null; } private Object readItemValue(Object value) { if (value instanceof JSONArray) { JSONArray array = (JSONArray) value; - Object[] content = new Object[array.length()]; - for (int i = 0; i < array.length(); i++) { + Object[] content = new Object[array.size()]; + for (int i = 0; i < array.size(); i++) { content[i] = array.get(i); } return content; @@ -176,20 +163,41 @@ private Object readItemValue(Object value) { return value; } - private JSONObject readJson(InputStream in, Charset charset) throws IOException { + private JSONObject readJson(InputStream in, Charset charset) throws IOException, ParseException { try { - StringBuilder out = new StringBuilder(); + StringWriter out = new StringWriter(); InputStreamReader reader = new InputStreamReader(in, charset); char[] buffer = new char[BUFFER_SIZE]; - int bytesRead = -1; + int bytesRead; while ((bytesRead = reader.read(buffer)) != -1) { - out.append(buffer, 0, bytesRead); + out.append(new String(buffer), 0, bytesRead); } - return new JSONObject(out.toString()); + JSONParser parser = new JSONParser(); + return (JSONObject) parser.parse(out.toString()); } finally { in.close(); } } + @SuppressWarnings("unchecked") + private T get(JSONObject source, String key, boolean mustExist) { + if (source.containsKey(key)) { + return (T) source.get(key); + } + + if (mustExist) { + throw new IllegalStateException("Key " + key + "not found."); + } + + return null; + } + + private T getOrNull(JSONObject source, String key) { + return get(source, key, false); + } + + private T getMustExist(JSONObject source, String key) { + return get(source, key, true); + } } diff --git a/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/JsonReaderTests.java b/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/JsonReaderTests.java index 488eab2bc064..78c7f6ea2c2d 100644 --- a/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/JsonReaderTests.java +++ b/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/JsonReaderTests.java @@ -16,11 +16,9 @@ package org.springframework.boot.configurationmetadata; -import java.io.IOException; import java.nio.charset.Charset; import java.util.List; -import org.json.JSONException; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -37,20 +35,20 @@ public class JsonReaderTests extends AbstractConfigurationMetadataTests { private final JsonReader reader = new JsonReader(); @Test - public void emptyMetadata() throws IOException { + public void emptyMetadata() throws Exception { RawConfigurationMetadata rawMetadata = readFor("empty"); assertThat(rawMetadata.getSources()).isEmpty(); assertThat(rawMetadata.getItems()).isEmpty(); } @Test - public void invalidMetadata() throws IOException { - this.thrown.expect(JSONException.class); + public void invalidMetadata() throws Exception { + this.thrown.expect(IllegalStateException.class); readFor("invalid"); } @Test - public void emptyGroupName() throws IOException { + public void emptyGroupName() throws Exception { RawConfigurationMetadata rawMetadata = readFor("empty-groups"); List items = rawMetadata.getItems(); assertThat(items).hasSize(2); @@ -62,7 +60,7 @@ public void emptyGroupName() throws IOException { } @Test - public void simpleMetadata() throws IOException { + public void simpleMetadata() throws Exception { RawConfigurationMetadata rawMetadata = readFor("foo"); List sources = rawMetadata.getSources(); assertThat(sources).hasSize(2); @@ -92,7 +90,7 @@ public void simpleMetadata() throws IOException { assertThat(hint.getId()).isEqualTo("spring.foo.counter"); assertThat(hint.getValueHints()).hasSize(1); ValueHint valueHint = hint.getValueHints().get(0); - assertThat(valueHint.getValue()).isEqualTo(42); + assertThat(valueHint.getValue()).isEqualTo(42L); assertThat(valueHint.getDescription()).isEqualTo( "Because that's the answer to any question, choose it. \nReally."); assertThat(valueHint.getShortDescription()) @@ -106,7 +104,7 @@ public void simpleMetadata() throws IOException { } @Test - public void metadataHints() throws IOException { + public void metadataHints() throws Exception { RawConfigurationMetadata rawMetadata = readFor("bar"); List hints = rawMetadata.getHints(); assertThat(hints).hasSize(1); @@ -133,7 +131,7 @@ public void metadataHints() throws IOException { } @Test - public void rootMetadata() throws IOException { + public void rootMetadata() throws Exception { RawConfigurationMetadata rawMetadata = readFor("root"); List sources = rawMetadata.getSources(); assertThat(sources).isEmpty(); @@ -144,7 +142,7 @@ public void rootMetadata() throws IOException { } @Test - public void deprecatedMetadata() throws IOException { + public void deprecatedMetadata() throws Exception { RawConfigurationMetadata rawMetadata = readFor("deprecated"); List items = rawMetadata.getItems(); assertThat(items).hasSize(3); @@ -171,7 +169,7 @@ public void deprecatedMetadata() throws IOException { assertThat(item3.getDeprecation()).isEqualTo(null); } - RawConfigurationMetadata readFor(String path) throws IOException { + RawConfigurationMetadata readFor(String path) throws Exception { return this.reader.read(getInputStreamFor(path), DEFAULT_CHARSET); }