From 257c36c00a16304c07e429d5ceda556548528cc9 Mon Sep 17 00:00:00 2001 From: Kalle Stenflo Date: Wed, 29 Mar 2017 11:50:42 +0200 Subject: [PATCH] Make ParseContext from JsonPath.using thread safe #187 --- .../java/com/jayway/jsonpath/JsonPath.java | 38 +++++---- .../com/jayway/jsonpath/ParseContext.java | 3 + .../jayway/jsonpath/internal/JsonContext.java | 82 +------------------ .../jsonpath/internal/ParseContextImpl.java | 82 +++++++++++++++++++ 4 files changed, 108 insertions(+), 97 deletions(-) create mode 100644 json-path/src/main/java/com/jayway/jsonpath/internal/ParseContextImpl.java diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java index d96cfd2b9..c66659cff 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java @@ -16,7 +16,7 @@ import com.jayway.jsonpath.internal.EvaluationContext; -import com.jayway.jsonpath.internal.JsonContext; +import com.jayway.jsonpath.internal.ParseContextImpl; import com.jayway.jsonpath.internal.Path; import com.jayway.jsonpath.internal.PathRef; import com.jayway.jsonpath.internal.Utils; @@ -499,7 +499,7 @@ public static T read(Object json, String jsonPath, Predicate... filters) { */ @SuppressWarnings({"unchecked"}) public static T read(String json, String jsonPath, Predicate... filters) { - return new JsonContext().parse(json).read(jsonPath, filters); + return new ParseContextImpl().parse(json).read(jsonPath, filters); } @@ -515,7 +515,7 @@ public static T read(String json, String jsonPath, Predicate... filters) { @SuppressWarnings({"unchecked"}) @Deprecated public static T read(URL jsonURL, String jsonPath, Predicate... filters) throws IOException { - return new JsonContext().parse(jsonURL).read(jsonPath, filters); + return new ParseContextImpl().parse(jsonURL).read(jsonPath, filters); } /** @@ -529,7 +529,7 @@ public static T read(URL jsonURL, String jsonPath, Predicate... filters) thr */ @SuppressWarnings({"unchecked"}) public static T read(File jsonFile, String jsonPath, Predicate... filters) throws IOException { - return new JsonContext().parse(jsonFile).read(jsonPath, filters); + return new ParseContextImpl().parse(jsonFile).read(jsonPath, filters); } /** @@ -543,7 +543,7 @@ public static T read(File jsonFile, String jsonPath, Predicate... filters) t */ @SuppressWarnings({"unchecked"}) public static T read(InputStream jsonInputStream, String jsonPath, Predicate... filters) throws IOException { - return new JsonContext().parse(jsonInputStream).read(jsonPath, filters); + return new ParseContextImpl().parse(jsonInputStream).read(jsonPath, filters); } @@ -555,13 +555,15 @@ public static T read(InputStream jsonInputStream, String jsonPath, Predicate /** - * Creates a {@link ParseContext} that can be used to parse a given JSON input. + * Creates a {@link ParseContext} that can be used to parse JSON input. The parse context + * is as thread safe as the underlying {@link JsonProvider}. Note that not all JsonProvider are + * thread safe. * * @param configuration configuration to use when parsing JSON * @return a parsing context based on given configuration */ public static ParseContext using(Configuration configuration) { - return new JsonContext(configuration); + return new ParseContextImpl(configuration); } /** @@ -572,7 +574,7 @@ public static ParseContext using(Configuration configuration) { */ @Deprecated public static ParseContext using(JsonProvider provider) { - return new JsonContext(Configuration.builder().jsonProvider(provider).build()); + return new ParseContextImpl(Configuration.builder().jsonProvider(provider).build()); } /** @@ -583,7 +585,7 @@ public static ParseContext using(JsonProvider provider) { * @return a read context */ public static DocumentContext parse(Object json) { - return new JsonContext().parse(json); + return new ParseContextImpl().parse(json); } /** @@ -594,7 +596,7 @@ public static DocumentContext parse(Object json) { * @return a read context */ public static DocumentContext parse(String json) { - return new JsonContext().parse(json); + return new ParseContextImpl().parse(json); } /** @@ -605,7 +607,7 @@ public static DocumentContext parse(String json) { * @return a read context */ public static DocumentContext parse(InputStream json) { - return new JsonContext().parse(json); + return new ParseContextImpl().parse(json); } /** @@ -616,7 +618,7 @@ public static DocumentContext parse(InputStream json) { * @return a read context */ public static DocumentContext parse(File json) throws IOException { - return new JsonContext().parse(json); + return new ParseContextImpl().parse(json); } /** @@ -627,7 +629,7 @@ public static DocumentContext parse(File json) throws IOException { * @return a read context */ public static DocumentContext parse(URL json) throws IOException { - return new JsonContext().parse(json); + return new ParseContextImpl().parse(json); } /** @@ -638,7 +640,7 @@ public static DocumentContext parse(URL json) throws IOException { * @return a read context */ public static DocumentContext parse(Object json, Configuration configuration) { - return new JsonContext(configuration).parse(json); + return new ParseContextImpl(configuration).parse(json); } /** @@ -649,7 +651,7 @@ public static DocumentContext parse(Object json, Configuration configuration) { * @return a read context */ public static DocumentContext parse(String json, Configuration configuration) { - return new JsonContext(configuration).parse(json); + return new ParseContextImpl(configuration).parse(json); } /** @@ -660,7 +662,7 @@ public static DocumentContext parse(String json, Configuration configuration) { * @return a read context */ public static DocumentContext parse(InputStream json, Configuration configuration) { - return new JsonContext(configuration).parse(json); + return new ParseContextImpl(configuration).parse(json); } /** @@ -671,7 +673,7 @@ public static DocumentContext parse(InputStream json, Configuration configuratio * @return a read context */ public static DocumentContext parse(File json, Configuration configuration) throws IOException { - return new JsonContext(configuration).parse(json); + return new ParseContextImpl(configuration).parse(json); } /** @@ -682,7 +684,7 @@ public static DocumentContext parse(File json, Configuration configuration) thro * @return a read context */ public static DocumentContext parse(URL json, Configuration configuration) throws IOException { - return new JsonContext(configuration).parse(json); + return new ParseContextImpl(configuration).parse(json); } private T resultByConfiguration(Object jsonObject, Configuration configuration, EvaluationContext evaluationContext) { diff --git a/json-path/src/main/java/com/jayway/jsonpath/ParseContext.java b/json-path/src/main/java/com/jayway/jsonpath/ParseContext.java index 12f3a34ff..7aad7292d 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/ParseContext.java +++ b/json-path/src/main/java/com/jayway/jsonpath/ParseContext.java @@ -19,6 +19,9 @@ import java.io.InputStream; import java.net.URL; +/** + * Parses JSON as specified by the used {@link com.jayway.jsonpath.spi.json.JsonProvider}. + */ public interface ParseContext { DocumentContext parse(String json); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java index f3d119345..e16e33d34 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java @@ -20,7 +20,6 @@ import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.MapFunction; import com.jayway.jsonpath.Option; -import com.jayway.jsonpath.ParseContext; import com.jayway.jsonpath.Predicate; import com.jayway.jsonpath.ReadContext; import com.jayway.jsonpath.TypeRef; @@ -29,11 +28,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; import java.util.LinkedList; import java.util.List; @@ -42,90 +36,20 @@ import static com.jayway.jsonpath.internal.Utils.notNull; import static java.util.Arrays.asList; -public class JsonContext implements ParseContext, DocumentContext { +public class JsonContext implements DocumentContext { private static final Logger logger = LoggerFactory.getLogger(JsonContext.class); private final Configuration configuration; - private Object json; + private final Object json; - public JsonContext() { - this(Configuration.defaultConfiguration()); - } - - public JsonContext(Configuration configuration) { - notNull(configuration, "configuration can not be null"); - this.configuration = configuration; - } - - private JsonContext(Object json, Configuration configuration) { + JsonContext(Object json, Configuration configuration) { notNull(json, "json can not be null"); notNull(configuration, "configuration can not be null"); this.configuration = configuration; this.json = json; } - //------------------------------------------------ - // - // ParseContext impl - // - //------------------------------------------------ - @Override - public DocumentContext parse(Object json) { - notNull(json, "json object can not be null"); - this.json = json; - return this; - } - - @Override - public DocumentContext parse(String json) { - notEmpty(json, "json string can not be null or empty"); - this.json = configuration.jsonProvider().parse(json); - return this; - } - - @Override - public DocumentContext parse(InputStream json) { - return parse(json, "UTF-8"); - } - - @Override - public DocumentContext parse(InputStream json, String charset) { - notNull(json, "json input stream can not be null"); - notNull(json, "charset can not be null"); - try { - this.json = configuration.jsonProvider().parse(json, charset); - return this; - } finally { - Utils.closeQuietly(json); - } - } - - @Override - public DocumentContext parse(File json) throws IOException { - notNull(json, "json file can not be null"); - FileInputStream fis = null; - try { - fis = new FileInputStream(json); - parse(fis); - } finally { - Utils.closeQuietly(fis); - } - return this; - } - - @Override - public DocumentContext parse(URL url) throws IOException { - notNull(url, "url can not be null"); - InputStream fis = null; - try { - fis = url.openStream(); - parse(fis); - } finally { - Utils.closeQuietly(fis); - } - return this; - } @Override public Configuration configuration() { diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/ParseContextImpl.java b/json-path/src/main/java/com/jayway/jsonpath/internal/ParseContextImpl.java new file mode 100644 index 000000000..976f84816 --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/ParseContextImpl.java @@ -0,0 +1,82 @@ +package com.jayway.jsonpath.internal; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.ParseContext; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import static com.jayway.jsonpath.internal.Utils.notEmpty; +import static com.jayway.jsonpath.internal.Utils.notNull; + +public class ParseContextImpl implements ParseContext { + + private final Configuration configuration; + + public ParseContextImpl() { + this(Configuration.defaultConfiguration()); + } + + public ParseContextImpl(Configuration configuration) { + this.configuration = configuration; + } + + @Override + public DocumentContext parse(Object json) { + notNull(json, "json object can not be null"); + return new JsonContext(json, configuration); + } + + @Override + public DocumentContext parse(String json) { + notEmpty(json, "json string can not be null or empty"); + Object obj = configuration.jsonProvider().parse(json); + return new JsonContext(obj, configuration); + } + + @Override + public DocumentContext parse(InputStream json) { + return parse(json, "UTF-8"); + } + + @Override + public DocumentContext parse(InputStream json, String charset) { + notNull(json, "json input stream can not be null"); + notNull(json, "charset can not be null"); + try { + Object obj = configuration.jsonProvider().parse(json, charset); + return new JsonContext(obj, configuration); + } finally { + Utils.closeQuietly(json); + } + } + + @Override + public DocumentContext parse(File json) throws IOException { + notNull(json, "json file can not be null"); + FileInputStream fis = null; + try { + fis = new FileInputStream(json); + return parse(fis); + } finally { + Utils.closeQuietly(fis); + } + } + + @Override + public DocumentContext parse(URL url) throws IOException { + notNull(url, "url can not be null"); + InputStream fis = null; + try { + fis = url.openStream(); + return parse(fis); + } finally { + Utils.closeQuietly(fis); + } + } + +}