Repository: johnzon Updated Branches: refs/heads/master b2d205738 -> 78ad82adb
JOHNZON-194 ensure jsonparser tolerates multiple close calls Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/78ad82ad Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/78ad82ad Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/78ad82ad Branch: refs/heads/master Commit: 78ad82adb99fc9083506dca9afc5fb3089bbf37c Parents: b2d2057 Author: Romain Manni-Bucau <[email protected]> Authored: Sun Nov 11 18:02:39 2018 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Sun Nov 11 18:02:39 2018 +0100 ---------------------------------------------------------------------- .../johnzon/core/JsonStreamParserImpl.java | 8 ++++ .../org/apache/johnzon/core/JsonParserTest.java | 41 ++++++++++++++++++++ 2 files changed, 49 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/johnzon/blob/78ad82ad/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java index cd6022e..18f0a1c 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java @@ -95,6 +95,8 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC private int arrayDepth = 0; + private boolean closed; + //minimal stack implementation private static final class StructureElement { private final StructureElement previous; @@ -973,6 +975,10 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC @Override public void close() { + if (closed) { + return; + } + bufferProvider.release(buffer); if (releaseFallBackCopyBufferLength) { valueProvider.release(fallBackCopyBuffer); @@ -982,6 +988,8 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC in.close(); } catch (final IOException e) { throw new JsonException("Unexpected IO exception " + e.getMessage(), e); + } finally { + closed = true; } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/78ad82ad/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java index fb84307..0eac634 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java @@ -31,9 +31,12 @@ import java.io.InputStream; import java.io.StringReader; import java.math.BigDecimal; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.NoSuchElementException; +import java.util.function.Function; import javax.json.Json; import javax.json.JsonArray; @@ -67,6 +70,44 @@ public class JsonParserTest { } @Test + public void avoidBufferStrategyLeaks() { + final Function<JsonParser, String> parse = parser -> { + final Collection<String> output = new ArrayList<>(); + Event e; + do { + e = parser.next(); + switch (e) { + case KEY_NAME: + output.add("KEY_NAME: " + parser.getString()); + break; + case VALUE_STRING: + output.add("VALUE_STRING: " + parser.getString()); + break; + default: + break; + } + } while (parser.hasNext()); + return String.join("/", output); + }; + final String jsonText1 = "{\"name\":\"App_1\", \"value\":\"value_1\"}"; + final String jsonText2 = "{\"name\":\"App_2\", \"value\":\"value_2\"}"; + final JsonParser jsonParser = Json.createParser(new ByteArrayInputStream(jsonText1.getBytes())); + jsonParser.close(); + jsonParser.close(); + + final JsonParser jsonParser1 = Json.createParser(new ByteArrayInputStream(jsonText1.getBytes())); + jsonParser1.next(); // write jsonParser1 buffer + final JsonParser jsonParser2 = Json.createParser(new ByteArrayInputStream(jsonText2.getBytes())); + jsonParser2.next(); // overwrite jsonParser1 buffer + + assertEquals("KEY_NAME: name/VALUE_STRING: App_1/KEY_NAME: value/VALUE_STRING: value_1", parse.apply(jsonParser1)); + assertEquals("KEY_NAME: name/VALUE_STRING: App_2/KEY_NAME: value/VALUE_STRING: value_2", parse.apply(jsonParser2)); + + jsonParser1.close(); + jsonParser2.close(); + } + + @Test public void emptyObject() { final JsonParser parser = Json.createParser(new StringReader("")); assertFalse(parser.hasNext());
