backporting changes from master to the JSON_P-1.0 branch fixes: #21 txs to jgallimore for the patch! Applied with slight changes.
This includes the following tickets, and likely a few more: JOHNZON-156 JOHNZON-142 JOHNZON-135 JOHNZON-133 JOHNZON-123 For more history please analyse the master branch for the original changes. Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/76fe13de Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/76fe13de Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/76fe13de Branch: refs/heads/maintenance_1.0.x Commit: 76fe13de8c50783613fb33ddaaa2838cdff77fc7 Parents: d344cbc Author: Mark Struberg <[email protected]> Authored: Fri May 4 21:33:18 2018 +0200 Committer: Mark Struberg <[email protected]> Committed: Fri May 4 21:33:18 2018 +0200 ---------------------------------------------------------------------- KEYS | 46 +++ NOTICE | 2 +- johnzon-core/pom.xml | 17 +- .../johnzon/core/AbstractJsonFactory.java | 4 +- .../core/CommentsJsonStreamParserImpl.java | 15 +- .../apache/johnzon/core/JohnzonJsonParser.java | 97 +++++ .../johnzon/core/JohnzonJsonParserImpl.java | 31 ++ .../johnzon/core/JsonArrayBuilderImpl.java | 15 +- .../org/apache/johnzon/core/JsonArrayImpl.java | 3 +- .../johnzon/core/JsonBuilderFactoryImpl.java | 2 + .../org/apache/johnzon/core/JsonDoubleImpl.java | 19 +- .../apache/johnzon/core/JsonGeneratorImpl.java | 36 +- .../apache/johnzon/core/JsonInMemoryParser.java | 28 +- .../org/apache/johnzon/core/JsonLongImpl.java | 11 +- .../org/apache/johnzon/core/JsonNumberImpl.java | 16 +- .../johnzon/core/JsonObjectBuilderImpl.java | 20 +- .../org/apache/johnzon/core/JsonObjectImpl.java | 12 +- .../johnzon/core/JsonParserFactoryImpl.java | 42 ++- .../apache/johnzon/core/JsonPointerUtil.java | 49 +++ .../apache/johnzon/core/JsonProviderImpl.java | 4 +- .../org/apache/johnzon/core/JsonReaderImpl.java | 110 ++++-- .../johnzon/core/JsonStreamParserImpl.java | 123 +++++-- .../org/apache/johnzon/core/JsonWriterImpl.java | 36 +- .../core/RFC4627AwareInputStreamReader.java | 36 +- .../org/apache/johnzon/core/SimpleStack.java | 4 +- .../apache/johnzon/core/BrokenDefaultTest.java | 107 ++++++ .../johnzon/core/JsonArrayBuilderImplTest.java | 1 + .../apache/johnzon/core/JsonArrayImplTest.java | 8 + .../johnzon/core/JsonBuilderFactoryTest.java | 44 +++ .../johnzon/core/JsonGeneratorImplTest.java | 14 + .../org/apache/johnzon/core/JsonNumberTest.java | 55 ++- .../johnzon/core/JsonObjectBuilderImplTest.java | 18 +- .../apache/johnzon/core/JsonObjectImplTest.java | 17 + .../org/apache/johnzon/core/JsonParserTest.java | 9 +- .../apache/johnzon/core/JsonReaderImplTest.java | 32 +- .../org/apache/johnzon/core/OverflowTest.java | 88 +++++ .../test/resources/json/jsonPointerTest.json | 15 + johnzon-distribution/pom.xml | 7 +- .../jaxrs/ConfigurableJohnzonProvider.java | 35 ++ .../johnzon/jaxrs/JohnzonMessageBodyReader.java | 6 +- .../johnzon/jaxrs/JohnzonMessageBodyWriter.java | 12 +- .../WildcardConfigurableJohnzonProvider.java | 39 +- .../johnzon/jaxrs/JohnzonProviderTest.java | 82 +++-- johnzon-jsonb/pom.xml | 40 +- .../jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java | 157 ++++++-- .../org/apache/johnzon/jsonb/JohnsonJsonb.java | 368 ------------------- .../apache/johnzon/jsonb/JohnzonBuilder.java | 282 ++++++++++---- .../org/apache/johnzon/jsonb/JohnzonJsonb.java | 368 +++++++++++++++++++ .../apache/johnzon/jsonb/JsonbAccessMode.java | 111 ++++-- .../java/org/apache/johnzon/jsonb/cdi/CDIs.java | 10 +- .../johnzon/jsonb/cdi/JohnzonCdiExtension.java | 8 +- .../jsonb/converter/JohnzonJsonbAdapter.java | 14 +- .../org/apache/johnzon/jsonb/AdapterTest.java | 20 +- .../johnzon/jsonb/AnnotationOrderTest.java | 77 ++++ .../apache/johnzon/jsonb/CdiAdapterTest.java | 4 +- .../johnzon/jsonb/ClassConverterTest.java | 2 +- .../jsonb/CustomParameterizedTypeTest.java | 104 ++++++ .../johnzon/jsonb/DefaultMappingTest.java | 6 +- .../jsonb/DynamicBufferResizingTest.java | 93 +++++ .../jsonb/FailOnUnknownPropertiesTest.java | 56 +++ .../jsonb/JohnzonConverterInJsonbTest.java | 134 +++++++ .../johnzon/jsonb/JohnzonIgnoreNestedTest.java | 65 ++++ .../org/apache/johnzon/jsonb/JsonbReadTest.java | 81 ++++ .../apache/johnzon/jsonb/JsonbTypesTest.java | 134 ++++++- .../apache/johnzon/jsonb/JsonbWriteTest.java | 45 +++ .../johnzon/jsonb/ObjectSerializationTest.java | 77 ++++ .../apache/johnzon/jsonb/SerializerTest.java | 24 +- .../johnzon/jsonb/jaxrs/JsonbJaxRsTest.java | 41 ++- johnzon-mapper/pom.xml | 14 + .../mapper/JohnzonDeduplicateObjects.java | 39 ++ .../johnzon/mapper/JohnzonIgnoreNested.java | 39 ++ .../java/org/apache/johnzon/mapper/Mapper.java | 135 +++++-- .../apache/johnzon/mapper/MapperBuilder.java | 68 +++- .../org/apache/johnzon/mapper/MapperConfig.java | 42 ++- .../johnzon/mapper/MappingGeneratorImpl.java | 155 +++++--- .../johnzon/mapper/MappingParserImpl.java | 220 +++++++---- .../org/apache/johnzon/mapper/Mappings.java | 86 +++-- .../johnzon/mapper/SerializeValueFilter.java | 28 ++ .../johnzon/mapper/access/AccessMode.java | 1 + .../johnzon/mapper/access/BaseAccessMode.java | 106 +----- .../johnzon/mapper/access/FieldAccessMode.java | 25 +- .../johnzon/mapper/access/MethodAccessMode.java | 18 +- .../mapper/internal/JsonPointerTracker.java | 71 ++++ .../johnzon/mapper/reflection/Generics.java | 97 +++++ .../apache/johnzon/core/TestBufferProvider.java | 2 +- .../johnzon/mapper/CircularObjectsTest.java | 298 +++++++++++++++ .../johnzon/mapper/CustomEnumCodecTest.java | 67 ++++ .../org/apache/johnzon/mapper/EnumTest.java | 30 +- .../org/apache/johnzon/mapper/GenericsTest.java | 52 +++ .../johnzon/mapper/JohnzonIgnoreNestedTest.java | 67 ++++ .../org/apache/johnzon/mapper/LiteralTest.java | 10 + .../apache/johnzon/mapper/MapperConfigTest.java | 2 +- .../org/apache/johnzon/mapper/MapperTest.java | 29 +- .../org/apache/johnzon/mapper/NullTest.java | 71 ++++ .../ObjectConverterWithAnnotationTest.java | 33 ++ .../johnzon/mapper/ObjectSerializationTest.java | 74 ++++ .../apache/johnzon/mapper/ObjectTypeTest.java | 47 ++- .../mapper/SerializeValueFilterTest.java | 52 +++ .../mapper/internal/JsonPointerTrackerTest.java | 39 ++ .../java/org/superbiz/ExtendMappingTest.java | 2 +- .../src/test/java/org/superbiz/Model.java | 29 ++ .../src/test/java/org/superbiz/ModelBase.java | 34 ++ .../test/java/org/superbiz/ModelSuperBase.java | 53 +++ .../java/org/superbiz/ModelSuperSuperBase.java | 48 +++ johnzon-maven-plugin/pom.xml | 2 +- johnzon-websocket/pom.xml | 46 ++- .../src/test/resources/arquillian.xml | 6 + jsonb-api/pom.xml | 36 -- jsonb-api/run_sigtest.sh | 18 - .../src/main/java/javax/json/bind/Jsonb.java | 51 --- .../main/java/javax/json/bind/JsonbBuilder.java | 50 --- .../main/java/javax/json/bind/JsonbConfig.java | 117 ------ .../java/javax/json/bind/JsonbException.java | 31 -- .../javax/json/bind/adapter/JsonbAdapter.java | 24 -- .../json/bind/annotation/JsonbAnnotation.java | 26 -- .../json/bind/annotation/JsonbCreator.java | 30 -- .../json/bind/annotation/JsonbDateFormat.java | 40 -- .../json/bind/annotation/JsonbNillable.java | 31 -- .../json/bind/annotation/JsonbNumberFormat.java | 40 -- .../json/bind/annotation/JsonbProperty.java | 35 -- .../bind/annotation/JsonbPropertyOrder.java | 31 -- .../json/bind/annotation/JsonbTransient.java | 32 -- .../json/bind/annotation/JsonbTypeAdapter.java | 32 -- .../bind/annotation/JsonbTypeDeserializer.java | 36 -- .../bind/annotation/JsonbTypeSerializer.java | 36 -- .../json/bind/annotation/JsonbVisibility.java | 34 -- .../json/bind/config/BinaryDataStrategy.java | 29 -- .../bind/config/PropertyNamingStrategy.java | 30 -- .../json/bind/config/PropertyOrderStrategy.java | 29 -- .../bind/config/PropertyVisibilityStrategy.java | 27 -- .../bind/serializer/DeserializationContext.java | 31 -- .../json/bind/serializer/JsonbDeserializer.java | 30 -- .../json/bind/serializer/JsonbSerializer.java | 25 -- .../bind/serializer/SerializationContext.java | 27 -- .../java/javax/json/bind/spi/JsonbProvider.java | 59 --- pom.xml | 217 +++++------ src/site/markdown/download.md | 93 +++++ src/site/markdown/index.md | 21 +- src/site/site.xml | 2 +- 139 files changed, 5051 insertions(+), 2224 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/KEYS ---------------------------------------------------------------------- diff --git a/KEYS b/KEYS index 1624147..3a40b1c 100644 --- a/KEYS +++ b/KEYS @@ -552,3 +552,49 @@ zxrmkygs1IMB6Q== =8P8F -----END PGP PUBLIC KEY BLOCK----- +pub 2048D/2678363C 2016-09-22 +uid Romain Manni-Bucau <[email protected]> +sig 3 2678363C 2016-09-22 Romain Manni-Bucau <[email protected]> +sub 2048g/25FC7483 2016-09-22 +sig 2678363C 2016-09-22 Romain Manni-Bucau <[email protected]> + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQMuBFfj3GARCACZnUOt5zI4juSDnIAkh7JvRsEZ2MkmhcxsUXHvruTxxJmdecV1 +YZdN6pdSl7LUCNhPv+I4v+Hl6fRtRcGmiRWV489PjyDKFbBL+C/DU2NtpGfmrP1t ++GKR6G/YQjTaJUJNKPMR2aRzB9Bi92y1LdSrF6+mFZ8w6s/XF2hfrLMR7HM3XDi2 +voH0KCmlCIsgKJjWt23t5c+zTH+FUH5jOeOhFw3QqUlTViVErp08/imlNWW0Hg8Y +tabQRGHiGMFvhdg+JPeMAOzeMPAglo297z8dNI/LKuFN/YbsDp2Aiu0/Tyj9Wp/Q +RfWa507UP+fsdAlkHBcQ6ko8Q5Kp7DITt2/zAQDDPfNwCDp3K9KHKh/47y1TEnEp +P5vqGf85BLRKI9uAywf9GQUyQsYobZKgz7tAPz8TAx4j4BJ9D9YmyOcSHnpP5mEf +t9T3lpYdskk/5ijmRiQUWhQek0Qw+KftCqYotEKmaigk1TDbjdO6aqw2OXsvpidZ +E7VSKHT7Kc7Ktn7IVX0N0/ssv8gAiWF7metc5xCkhWiM0KwdlhOeKs5DxeRTyvfs +TKLvEFPl1gs3LHMzHVjjUTkp0eJ/w7OFfNl1mFc+xc9J3w+8RC8bI33IxN1ZxU2L +dEvFEVkCNl+R2dl6WVUrSRkYMr2ENROaA62kN4DsPFBtx408vbB5+yX7P/iDe4Fx +b32h0fdz7OOEvco8AljcvJryCOP8yMM+nXQQkwOkTQf9HjUJ3oKnbm7IFxq6cYJg +3UT1EYcThWYCeMQxp58RuA1ZxXPWhLea4I58U+W9JTyb38AnEFG/0MKK7YpEteu1 +VXrIJJ6+rEBntj5f0yVRdJVKkZDm9FOy6dO6TJmd5wg3F/HadLDtXn5aR3rMudeg +BOg9/EFYyJLEXvvSsMdk5V7Z07BuG0gsBIRuh9QH0oG/i56tXPNFznylvXhL4K/v +uNEZhccQlfCzYlGA7kGe6iVNStyApvsUcItrACj2xnlCJS+KNZ/HQvfFkrH8gc1W +XoNtWNRL290XG82QVIisubMENcluHrXHFOXE64aTzpaxi/x5/81limcETRh8GnrM +2rQrUm9tYWluIE1hbm5pLUJ1Y2F1IDxybWFubmlidWNhdUBhcGFjaGUub3JnPoh6 +BBMRCAAiBQJX49xgAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBnwSJ6 +Jng2PADeAQCOQBnAYrM3sVFrfOSLHbpUl9cs+2ZJQR93n04wi16dHQD/eX9IAzix +YPq6moB4d2pXMxZGvX2KjCTK3LMuDqJH3Xi5Ag0EV+PcYBAIAIeYsSFzYkaIhSE0 +x+UXN3O3hCjp8408ZhAd6N/aeTtSOnyuCMXYQJzFxC+HzGehzG/GB+Gzep78IydM +TELyyjGWXd/fJ1zEY1VpKEsMStzWQccO0nHMIqIg4w7caJdWpB69Gnmo4vjSvhDw +d13HKCSf4ypR50YU4qQPumACl/qcBtgiV4hJGasp+93Ua8CP0Yv5h4Llc/Rdd090 +GXbV5kDK2+gryNR1P5BQstmpgIf0AY1LwHQ5+CvjDhn0RZW7EdbAMx6yl9cpTm54 +s68wRp/8Xz4/YahFnfMQoq23DDF3T3ia2VnkLHEudg92RvSw4I0XiSJlrGTjml4w +aVosMjcAAwUH/RBWGZr7prNHjDd5udf+SUzSa7JG53000z04swi8wWpe/aBYpip5 +GHemgOsJC7P+MFcXYlMUCnJ4/hIzPhYmzy2D1tXgkr/o6EquZCsHl+vtyBXZvAfv +spVbRDePDe9CvVRQB4PaQz3cNG6yncp2du0E/2EojctdD62vMHhPf1S+2H/BPHXG +8fWI9dphvaU5g4l1Ah5/cPDptvY/UAC/w7hh7+Fl8Is0xVP5opdeIacvWGUHfcKa +SvohQwzB9kYJyS5Dru1nTiMNo0RYZ6ANLeWiF+gJHmIqdHE3xPSXOQ+tMFdywRf0 ++qVKAsJUd/9f7X8h6o75OyPCl9uFlFY012OIYQQYEQgACQUCV+PcYAIbDAAKCRBn +wSJ6Jng2POYtAQC5jGmB/Lt2D4Gfp0E6kjWj2U8uXeZCkFCO+uY5ZzKflgEAhrmM +mfoA5aIoZWJRK1AzuuJ3BKl8ViTAgrhazZ1B+9w= +=s6vt +-----END PGP PUBLIC KEY BLOCK----- + http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/NOTICE ---------------------------------------------------------------------- diff --git a/NOTICE b/NOTICE index f44f3b6..cb43ecb 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Johnzon -Copyright 2014-2017 The Apache Software Foundation +Copyright 2014-2018 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/pom.xml ---------------------------------------------------------------------- diff --git a/johnzon-core/pom.xml b/johnzon-core/pom.xml index 9d0183b..f0a593a 100644 --- a/johnzon-core/pom.xml +++ b/johnzon-core/pom.xml @@ -27,9 +27,24 @@ <artifactId>johnzon-core</artifactId> <name>Johnzon :: Core</name> + <packaging>bundle</packaging> <properties> <staging.directory>${project.parent.reporting.outputDirectory}</staging.directory> </properties> - <packaging>bundle</packaging> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Require-Capability>osgi.extender;filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability> + <Provide-Capability>osgi.serviceloader;osgi.serviceloader=javax.json.spi.JsonProvider</Provide-Capability> + </instructions> + </configuration> + </plugin> + </plugins> + </build> </project> http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java b/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java index 4ab42d5..3629293 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/AbstractJsonFactory.java @@ -26,12 +26,12 @@ import java.util.Locale; import java.util.Map; import java.util.logging.Logger; -public abstract class AbstractJsonFactory implements Serializable{ +public abstract class AbstractJsonFactory implements Serializable { protected final Logger logger = Logger.getLogger(this.getClass().getName()); public static final String BUFFER_STRATEGY = "org.apache.johnzon.buffer-strategy"; - public static final BufferStrategy DEFAULT_BUFFER_STRATEGY = BufferStrategy.QUEUE; + public static final BufferStrategy DEFAULT_BUFFER_STRATEGY = BufferStrategy.valueOf(System.getProperty(BUFFER_STRATEGY, "QUEUE")); protected final Map<String, Object> internalConfig = new HashMap<String, Object>(); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java index 39e9f1c..f9d298e 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java @@ -26,23 +26,26 @@ public class CommentsJsonStreamParserImpl extends JsonStreamParserImpl { public CommentsJsonStreamParserImpl(final InputStream inputStream, final int maxStringLength, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final BufferStrategy.BufferProvider<char[]> valueBuffer) { - super(inputStream, maxStringLength, bufferProvider, valueBuffer); + final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { + super(inputStream, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } public CommentsJsonStreamParserImpl(final InputStream inputStream, final Charset encoding, final int maxStringLength, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final BufferStrategy.BufferProvider<char[]> valueBuffer) { - super(inputStream, encoding, maxStringLength, bufferProvider, valueBuffer); + final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { + super(inputStream, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } public CommentsJsonStreamParserImpl(final Reader reader, final int maxStringLength, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final BufferStrategy.BufferProvider<char[]> valueBuffer) { - super(reader, maxStringLength, bufferProvider, valueBuffer); + final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { + super(reader, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } @Override http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParser.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParser.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParser.java new file mode 100644 index 0000000..b2a55a0 --- /dev/null +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParser.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.johnzon.core; + +import java.math.BigDecimal; +import javax.json.stream.JsonLocation; +import javax.json.stream.JsonParser; + +/** + * JsonParser with extended functionality + */ +public interface JohnzonJsonParser extends JsonParser { + + boolean isNotTooLong(); + + /** + * @return the _current_ Event. That's the one returned by the previous call to {@link #next()} + * but without propagating the Event pointer to the next entry. + */ + Event current(); + + public static class JohnzonJsonParserWrapper implements JohnzonJsonParser { + public Event current() { + throw new UnsupportedOperationException("getting the current JsonParser Event is not supported"); + } + + private final JsonParser jsonParser; + + public JohnzonJsonParserWrapper(JsonParser jsonParser) { + this.jsonParser = jsonParser; + } + + @Override + public boolean isNotTooLong() { + return true; + } + + @Override + public boolean hasNext() { + return jsonParser.hasNext(); + } + + @Override + public Event next() { + return jsonParser.next(); + } + + @Override + public String getString() { + return jsonParser.getString(); + } + + @Override + public boolean isIntegralNumber() { + return jsonParser.isIntegralNumber(); + } + + @Override + public int getInt() { + return jsonParser.getInt(); + } + + @Override + public long getLong() { + return jsonParser.getLong(); + } + + @Override + public BigDecimal getBigDecimal() { + return jsonParser.getBigDecimal(); + } + + @Override + public JsonLocation getLocation() { + return jsonParser.getLocation(); + } + + @Override + public void close() { + jsonParser.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java new file mode 100644 index 0000000..356399b --- /dev/null +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.johnzon.core; + + +/** + * Base parser which handles higher level operations which are + * mixtures of Reader and Parsers like {@code getObject(), getValue(), getArray()} + */ +public abstract class JohnzonJsonParserImpl implements JohnzonJsonParser { + + /** + * @return {@code true} if we are currently inside an array + */ + protected abstract boolean isInArray(); + +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java index 913c22a..436a035 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java @@ -97,30 +97,25 @@ class JsonArrayBuilderImpl implements JsonArrayBuilder, Serializable { addValue(builder.build()); return this; } - - private void addValue(JsonValue value){ + + private void addValue(JsonValue value) { if (value == null) { throw npe(); } - + if(tmpList==null){ tmpList=new ArrayList<JsonValue>(); } - + tmpList.add(value); } @Override public JsonArray build() { - if(tmpList == null) { return new JsonArrayImpl(Collections.EMPTY_LIST); - } else { - List<JsonValue> dump = (Collections.unmodifiableList(tmpList)); - tmpList=null; - return new JsonArrayImpl(dump); } - + return new JsonArrayImpl(Collections.unmodifiableList(tmpList)); } private static NullPointerException npe() { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java index cfb563d..1d880c7 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayImpl.java @@ -179,8 +179,7 @@ class JsonArrayImpl extends AbstractList<JsonValue> implements JsonArray, Serial @Override public boolean equals(final Object obj) { - return JsonArrayImpl.class.isInstance(obj) - && unmodifieableBackingList.equals(JsonArrayImpl.class.cast(obj).unmodifieableBackingList); + return JsonArray.class.isInstance(obj) && super.equals(obj); } @Override http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java index 121f18f..3d1ff1c 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java @@ -60,8 +60,10 @@ class JsonBuilderFactoryImpl implements JsonBuilderFactory { return new JsonArrayBuilderImpl(); } + @Override public Map<String, ?> getConfigInUse() { return Collections.unmodifiableMap(internalConfig); } + } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonDoubleImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonDoubleImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonDoubleImpl.java index cff63c0..bcce401 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonDoubleImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonDoubleImpl.java @@ -26,6 +26,8 @@ import java.math.BigInteger; final class JsonDoubleImpl implements JsonNumber, Serializable { private final double value; + private Integer hashCode = null; + JsonDoubleImpl(final double value) { if(Double.isInfinite(value) || Double.isNaN(value)) { @@ -47,6 +49,7 @@ final class JsonDoubleImpl implements JsonNumber, Serializable { @Override public int intValueExact() { + checkFractionalPart(); return intValue(); } @@ -57,6 +60,7 @@ final class JsonDoubleImpl implements JsonNumber, Serializable { @Override public long longValueExact() { + checkFractionalPart(); return (long) value; } @@ -92,11 +96,24 @@ final class JsonDoubleImpl implements JsonNumber, Serializable { @Override public int hashCode() { - return Double.valueOf(value).hashCode(); + if (hashCode == null) { + hashCode = bigDecimalValue().hashCode(); + } + + return hashCode; } @Override public boolean equals(final Object obj) { + if (JsonDoubleImpl.class.isInstance(obj)) { + return JsonDoubleImpl.class.cast(obj).value == value; + } return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).doubleValue() == value; } + + private void checkFractionalPart() { + if ((value % 1) != 0) { + throw new ArithmeticException("Not an int/long, use other value readers"); + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java index e1371e5..5ef026a 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java @@ -430,6 +430,23 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { return this; } + public JsonGenerator writeKey(final String key) { + final GeneratorState currentState = currentState(); + if (!currentState.acceptsKey) { + throw new JsonGenerationException("state " + currentState + " does not accept a key"); + } + if (currentState == GeneratorState.IN_OBJECT) { + justWrite(COMMA_CHAR); + writeEol(); + } + + writeIndent(); + + writeCachedKey(key); + state.push(GeneratorState.AFTER_KEY); + return this; + } + @Override public void close() { try { @@ -442,8 +459,9 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { writer.close(); } catch (final IOException e) { throw new JsonException(e.getMessage(), e); + } finally { + bufferProvider.release(buffer); } - bufferProvider.release(buffer); } } @@ -650,22 +668,6 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { return state.peek(); } - private void writeKey(final String key) { - final GeneratorState currentState = currentState(); - if (!currentState.acceptsKey) { - throw new IllegalStateException("state " + currentState + " does not accept a key"); - } - if (currentState == GeneratorState.IN_OBJECT) { - justWrite(COMMA_CHAR); - writeEol(); - } - - writeIndent(); - - writeCachedKey(key); - state.push(GeneratorState.AFTER_KEY); - } - private void writeValueAsJsonString(final String value) { prepareValue(); final GeneratorState peek = state.peek(); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java index 9137139..f94e437 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java @@ -30,14 +30,14 @@ import javax.json.JsonString; import javax.json.JsonValue; import javax.json.JsonValue.ValueType; import javax.json.stream.JsonLocation; -import javax.json.stream.JsonParser; -class JsonInMemoryParser implements JsonParser { +class JsonInMemoryParser extends JohnzonJsonParserImpl { private final SimpleStack<Iterator<Event>> stack = new SimpleStack<Iterator<Event>>(); private Event currentEvent; private JsonValue currentValue; + private int arrayDepth = 0; private class ArrayIterator implements Iterator<Event> { @@ -171,6 +171,19 @@ class JsonInMemoryParser implements JsonParser { } + @Override + public Event current() { + if (currentEvent == null && hasNext()) { + next(); + } + return currentEvent; + } + + @Override + protected boolean isInArray() { + return arrayDepth > 0; + } + private static Event getEvent(final ValueType value) { switch (value) { @@ -213,6 +226,12 @@ class JsonInMemoryParser implements JsonParser { currentEvent = stack.peek().next(); + if (currentEvent == Event.START_ARRAY) { + arrayDepth++; + } else if (currentEvent == Event.END_ARRAY) { + arrayDepth--; + } + return currentEvent; } @@ -233,6 +252,11 @@ class JsonInMemoryParser implements JsonParser { } @Override + public boolean isNotTooLong() { + return true; + } + + @Override public int getInt() { if (currentEvent != Event.VALUE_NUMBER) { throw new IllegalStateException("getInt is for numbers"); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonLongImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonLongImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonLongImpl.java index 4068d9b..2a5f480 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonLongImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonLongImpl.java @@ -25,6 +25,7 @@ import java.math.BigInteger; public final class JsonLongImpl implements JsonNumber, Serializable { private final long value; + private Integer hashCode = null; JsonLongImpl(final long value) { this.value = value; @@ -87,11 +88,17 @@ public final class JsonLongImpl implements JsonNumber, Serializable { @Override public int hashCode() { - return (int) value; + if (hashCode == null) { + hashCode = bigDecimalValue().hashCode(); + } + return hashCode; } @Override public boolean equals(final Object obj) { - return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).longValue() == value; + if (JsonLongImpl.class.isInstance(obj)) { + return JsonLongImpl.class.cast(obj).value == value; + } + return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).bigDecimalValue().equals(bigDecimalValue()); } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java index 9ad7752..e114263 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java @@ -28,10 +28,10 @@ final class JsonNumberImpl implements JsonNumber, Serializable { private transient Integer hashCode = null; JsonNumberImpl(final BigDecimal decimal) { - if(decimal == null) { + if (decimal == null) { throw new NullPointerException("decimal must not be null"); } - + this.value = decimal; } @@ -47,6 +47,7 @@ final class JsonNumberImpl implements JsonNumber, Serializable { @Override public int intValueExact() { + checkFractionalPart(); return value.intValueExact(); } @@ -57,6 +58,7 @@ final class JsonNumberImpl implements JsonNumber, Serializable { @Override public long longValueExact() { + checkFractionalPart(); return value.longValueExact(); } @@ -92,10 +94,10 @@ final class JsonNumberImpl implements JsonNumber, Serializable { @Override public int hashCode() { - Integer h=hashCode; + Integer h = hashCode; if (h == null) { h = value.hashCode(); - hashCode=h; + hashCode = h; } return h; } @@ -104,4 +106,10 @@ final class JsonNumberImpl implements JsonNumber, Serializable { public boolean equals(final Object obj) { return JsonNumber.class.isInstance(obj) && JsonNumber.class.cast(obj).bigDecimalValue().equals(value); } + + private void checkFractionalPart() { + if (value.remainder(BigDecimal.ONE).doubleValue() != 0) { + throw new ArithmeticException("Not an int/long, use other value readers"); + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java index d625383..c75d827 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java @@ -30,7 +30,7 @@ import java.util.LinkedHashMap; import java.util.Map; class JsonObjectBuilderImpl implements JsonObjectBuilder, Serializable { - private Map<String, JsonValue> tmpMap; + private Map<String, JsonValue> attributeMap = new LinkedHashMap<String, JsonValue>(); @Override public JsonObjectBuilder add(final String name, final JsonValue value) { @@ -97,31 +97,23 @@ class JsonObjectBuilderImpl implements JsonObjectBuilder, Serializable { putValue(name, builder.build()); return this; } - + private void putValue(String name, JsonValue value){ if(name == null || value == null) { - throw npe(); + throw new NullPointerException("name or value/builder must not be null"); } - if(tmpMap==null){ - tmpMap=new LinkedHashMap<String, JsonValue>(); - } - - tmpMap.put(name, value); + attributeMap.put(name, value); } - private static NullPointerException npe() { - return new NullPointerException("name or value/builder must not be null"); - } @Override public JsonObject build() { - if(tmpMap==null) { + if(attributeMap == null || attributeMap.isEmpty()) { return new JsonObjectImpl(Collections.EMPTY_MAP); } else { - Map<String, JsonValue> dump = (Collections.unmodifiableMap(tmpMap)); - tmpMap=null; + Map<String, JsonValue> dump = (Collections.unmodifiableMap(attributeMap)); return new JsonObjectImpl(dump); } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java index 263f43e..bb3a5ae 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectImpl.java @@ -109,7 +109,14 @@ final class JsonObjectImpl extends AbstractMap<String, JsonValue> implements Jso @Override public boolean getBoolean(final String name) { - return JsonValue.TRUE.equals(valueOrExcpetion(name, JsonValue.class)); + final JsonValue obj = valueOrExcpetion(name, JsonValue.class); + if (JsonValue.TRUE == obj) { + return true; + } + if (JsonValue.FALSE == obj) { + return false; + } + throw new ClassCastException("Wrong value for a boolean: " + obj); } @Override @@ -117,9 +124,8 @@ final class JsonObjectImpl extends AbstractMap<String, JsonValue> implements Jso final Object v = value(name, JsonValue.class); if (v != null) { return JsonValue.TRUE.equals(v) || !JsonValue.FALSE.equals(v) && defaultValue; - } else { - return defaultValue; } + return defaultValue; } @Override http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java index c57f144..440b4cb 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java @@ -18,8 +18,10 @@ */ package org.apache.johnzon.core; -import static java.util.Arrays.asList; - +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParserFactory; import java.io.InputStream; import java.io.Reader; import java.nio.charset.Charset; @@ -27,15 +29,13 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; -import javax.json.JsonArray; -import javax.json.JsonObject; -import javax.json.stream.JsonParser; -import javax.json.stream.JsonParserFactory; +import static java.util.Arrays.asList; public class JsonParserFactoryImpl extends AbstractJsonFactory implements JsonParserFactory { public static final String MAX_STRING_LENGTH = "org.apache.johnzon.max-string-length"; - public static final int DEFAULT_MAX_STRING_LENGTH = Integer.getInteger(MAX_STRING_LENGTH, 10 * 1024 * 1024); //10m + public static final int DEFAULT_MAX_STRING_LENGTH = Integer.getInteger(MAX_STRING_LENGTH, 256 * 1024); //256kB + public static final String AUTO_ADJUST_STRING_BUFFER = "org.apache.johnzon.auto-adjust-buffer"; public static final String BUFFER_LENGTH = "org.apache.johnzon.default-char-buffer"; public static final int DEFAULT_BUFFER_LENGTH = Integer.getInteger(BUFFER_LENGTH, 64 * 1024); //64k @@ -43,13 +43,14 @@ public class JsonParserFactoryImpl extends AbstractJsonFactory implements JsonPa public static final boolean DEFAULT_SUPPORTS_COMMENT = Boolean.getBoolean(SUPPORTS_COMMENTS); //default is false; static final Collection<String> SUPPORTED_CONFIG_KEYS = asList( - BUFFER_STRATEGY, MAX_STRING_LENGTH, BUFFER_LENGTH, SUPPORTS_COMMENTS + BUFFER_STRATEGY, MAX_STRING_LENGTH, BUFFER_LENGTH, SUPPORTS_COMMENTS, AUTO_ADJUST_STRING_BUFFER ); private final int maxSize; private final BufferStrategy.BufferProvider<char[]> bufferProvider; private final BufferStrategy.BufferProvider<char[]> valueBufferProvider; private final boolean supportsComments; + private final boolean autoAdjustBuffers; JsonParserFactoryImpl(final Map<String, ?> config) { super(config, SUPPORTED_CONFIG_KEYS, null); @@ -63,30 +64,31 @@ public class JsonParserFactoryImpl extends AbstractJsonFactory implements JsonPa this.bufferProvider = getBufferProvider().newCharProvider(bufferSize); this.valueBufferProvider = getBufferProvider().newCharProvider(maxSize); this.supportsComments = getBool(SUPPORTS_COMMENTS, DEFAULT_SUPPORTS_COMMENT); + this.autoAdjustBuffers = getBool(AUTO_ADJUST_STRING_BUFFER, true); } - private JsonParser getDefaultJsonParserImpl(final InputStream in) { + private JsonStreamParserImpl getDefaultJsonParserImpl(final InputStream in) { if (supportsComments) { - return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider); + return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } //UTF Auto detection RFC 4627 - return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider); + return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } - private JsonParser getDefaultJsonParserImpl(final InputStream in, final Charset charset) { + private JsonStreamParserImpl getDefaultJsonParserImpl(final InputStream in, final Charset charset) { if (supportsComments) { - return new CommentsJsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider); + return new CommentsJsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } //use provided charset - return new JsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider); + return new JsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } - private JsonParser getDefaultJsonParserImpl(final Reader in) { + private JsonStreamParserImpl getDefaultJsonParserImpl(final Reader in) { if (supportsComments) { - return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider); + return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } //no charset necessary - return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider); + return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers); } @Override @@ -121,15 +123,15 @@ public class JsonParserFactoryImpl extends AbstractJsonFactory implements JsonPa return Collections.unmodifiableMap(internalConfig); } - public JsonParser createInternalParser(final InputStream in) { + public JsonStreamParserImpl createInternalParser(final InputStream in) { return getDefaultJsonParserImpl(in); } - public JsonParser createInternalParser(final InputStream in, final Charset charset) { + public JsonStreamParserImpl createInternalParser(final InputStream in, final Charset charset) { return getDefaultJsonParserImpl(in, charset); } - public JsonParser createInternalParser(final Reader reader) { + public JsonStreamParserImpl createInternalParser(final Reader reader) { return getDefaultJsonParserImpl(reader); } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerUtil.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerUtil.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerUtil.java new file mode 100644 index 0000000..91bc9c2 --- /dev/null +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerUtil.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.johnzon.core; + +public class JsonPointerUtil { + + private JsonPointerUtil() { + + } + + /** + * Transforms "~" to "~0" and then "/" to "~1" + */ + public static String encode(String s) { + if (s == null || s.length() == 0) { + return s; + } + + return s.replace("~", "~0").replace("/", "~1"); + } + + /** + * Transforms "~1" to "/" and then "~0" to "~", + */ + public static String decode(String s) { + if (s == null || s.length() == 0) { + return s; + } + + return s.replace("~1", "/").replace("~0", "~"); + } + +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java index d1bbec6..86828c0 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java @@ -115,13 +115,13 @@ public class JsonProviderImpl extends JsonProvider implements Serializable { public JsonBuilderFactory createBuilderFactory(final Map<String, ?> stringMap) { return DELEGATE.createBuilderFactory(stringMap); } - + static class JsonProviderDelegate extends JsonProvider { private final JsonReaderFactory readerFactory = new JsonReaderFactoryImpl(null); private final JsonParserFactory parserFactory = new JsonParserFactoryImpl(null); private final JsonGeneratorFactory generatorFactory = new JsonGeneratorFactoryImpl(null); private final JsonWriterFactory writerFactory = new JsonWriterFactoryImpl(null); - private final JsonBuilderFactory builderFactory = new JsonBuilderFactoryImpl(null); + private final JsonBuilderFactoryImpl builderFactory = new JsonBuilderFactoryImpl(null); @Override public JsonParser createParser(final InputStream in) { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java index b0107ee..3e8a0fb 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java @@ -18,6 +18,7 @@ */ package org.apache.johnzon.core; + import javax.json.JsonArray; import javax.json.JsonArrayBuilder; import javax.json.JsonNumber; @@ -30,11 +31,29 @@ import javax.json.stream.JsonParser; import javax.json.stream.JsonParsingException; public class JsonReaderImpl implements JsonReader { - private final JsonParser parser; + private final JohnzonJsonParser parser; private boolean closed = false; + private boolean subStreamReader; + public JsonReaderImpl(final JsonParser parser) { - this.parser = parser; + this(parser, false); + } + + /** + * + * @param parser + * @param subStreamReader {@code true} if the Stream already got started and the first + * operation should not be next() but {@link JohnzonJsonParser#current()} instead. + */ + public JsonReaderImpl(final JsonParser parser, boolean subStreamReader) { + if (parser instanceof JohnzonJsonParser) { + this.parser = (JohnzonJsonParser) parser; + } else { + this.parser = new JohnzonJsonParser.JohnzonJsonParserWrapper(parser); + } + + this.subStreamReader = subStreamReader; } @Override @@ -42,62 +61,83 @@ public class JsonReaderImpl implements JsonReader { return JsonStructure.class.cast(readValue()); } - //@Override public JsonValue readValue() { checkClosed(); if (!parser.hasNext()) { throw new IllegalStateException("Nothing to read"); } - final JsonParser.Event next = parser.next(); + + + JsonParser.Event next; + if (subStreamReader) { + next = parser.current(); + } else { + next = parser.next(); + } + switch (next) { case START_OBJECT: final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(); parseObject(objectBuilder); - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); } - close(); return objectBuilder.build(); case START_ARRAY: final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(); parseArray(arrayBuilder); - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); } - close(); return arrayBuilder.build(); case VALUE_STRING: - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); - } final JsonStringImpl string = new JsonStringImpl(parser.getString()); - close(); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); + } return string; case VALUE_FALSE: - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); } - close(); return JsonValue.FALSE; case VALUE_TRUE: - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); } - close(); return JsonValue.TRUE; case VALUE_NULL: - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); } - close(); return JsonValue.NULL; case VALUE_NUMBER: - if (parser.hasNext()) { - throw new JsonParsingException("Expected end of file", parser.getLocation()); - } final JsonNumber number = new JsonNumberImpl(parser.getBigDecimal()); - close(); + if (!subStreamReader) { + if (parser.hasNext()) { + throw new JsonParsingException("Expected end of file", parser.getLocation()); + } + close(); + } return number; default: close(); @@ -107,12 +147,22 @@ public class JsonReaderImpl implements JsonReader { @Override public JsonObject readObject() { - return JsonObject.class.cast(read()); + final JsonStructure read = read(); + checkType(JsonObject.class, read); + return JsonObject.class.cast(read); } @Override public JsonArray readArray() { - return JsonArray.class.cast(read()); + final JsonStructure read = read(); + checkType(JsonArray.class, read); + return JsonArray.class.cast(read); + } + + private void checkType(final Class<?> expected, final JsonStructure read) { + if (!expected.isInstance(read)) { + throw new JsonParsingException("Expecting " + expected + " but got " + read, parser.getLocation()); + } } @Override @@ -151,7 +201,7 @@ public class JsonReaderImpl implements JsonReader { break; case VALUE_NUMBER: - if (parser.isIntegralNumber()) { + if (parser.isIntegralNumber() && parser.isNotTooLong()) { builder.add(key, new JsonLongImpl(parser.getLong())); } else { builder.add(key, new JsonNumberImpl(parser.getBigDecimal())); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/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 876ec78..4d0571a 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 @@ -20,18 +20,17 @@ package org.apache.johnzon.core; import javax.json.JsonException; import javax.json.stream.JsonLocation; -import javax.json.stream.JsonParser; import javax.json.stream.JsonParsingException; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; import java.math.BigDecimal; import java.nio.charset.Charset; import java.util.NoSuchElementException; //This class represents either the Json tokenizer and the Json parser. -public class JsonStreamParserImpl implements JsonChars, JsonParser{ +public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonChars { + private final boolean autoAdjust; //the main buffer where the stream will be buffered private final char[] buffer; @@ -63,11 +62,12 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //we use a byte here, because comparing bytes //is more efficient than comparing enums //Additionally we handle internally two more event: COMMA_EVENT and KEY_SEPARATOR_EVENT - private byte previousEvent; + private byte previousEvent = -1; //this buffer is used to store current String or Number value in case that //within the value a buffer boundary is crossed or the string contains escaped characters - private final char[] fallBackCopyBuffer; + private char[] fallBackCopyBuffer; + private boolean releaseFallBackCopyBufferLength = true; private int fallBackCopyBufferLength; // location (line, column, offset) @@ -93,6 +93,8 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //Stack can cause out of memory issues when the nesting depth of a Json stream is too deep. private StructureElement currentStructureElement = null; + private int arrayDepth = 0; + //minimal stack implementation private static final class StructureElement { private final StructureElement previous; @@ -107,27 +109,31 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //detect charset according to RFC 4627 public JsonStreamParserImpl(final InputStream inputStream, final int maxStringLength, - final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer) { + final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { - this(inputStream, null, null, maxStringLength, bufferProvider, valueBuffer); + this(inputStream, null, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } //use charset provided public JsonStreamParserImpl(final InputStream inputStream, final Charset encoding, final int maxStringLength, - final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer) { + final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { - this(inputStream, null, encoding, maxStringLength, bufferProvider, valueBuffer); + this(inputStream, null, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } public JsonStreamParserImpl(final Reader reader, final int maxStringLength, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final BufferStrategy.BufferProvider<char[]> valueBuffer) { + final BufferStrategy.BufferProvider<char[]> valueBuffer, final boolean autoAdjust) { - this(null, reader, null, maxStringLength, bufferProvider, valueBuffer); + this(null, reader, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust); } private JsonStreamParserImpl(final InputStream inputStream, final Reader reader, final Charset encoding, final int maxStringLength, - final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer) { + final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer, + final boolean autoAdjust) { + this.autoAdjust = autoAdjust; this.maxValueLength = maxStringLength <= 0 ? 8192 : maxStringLength; this.fallBackCopyBuffer = valueBuffer.newBuffer(); this.buffer = bufferProvider.newBuffer(); @@ -140,11 +146,8 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ if (reader != null) { this.in = reader; - } else if (encoding == null) { - this.in = new RFC4627AwareInputStreamReader(inputStream); - } else { - this.in = new InputStreamReader(inputStream, encoding.newDecoder()); + this.in = new RFC4627AwareInputStreamReader(inputStream, encoding); } } @@ -155,29 +158,52 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //copy content between "start" and "end" from buffer to value buffer private void copyCurrentValue() { + final int length = endOfValueInBuffer - startOfValueInBuffer; + if (length > 0) { - if ((endOfValueInBuffer - startOfValueInBuffer) > 0) { - - if ((endOfValueInBuffer - startOfValueInBuffer) > maxValueLength) { + if (length > maxValueLength) { throw tmc(); } - System.arraycopy(buffer, startOfValueInBuffer, fallBackCopyBuffer, fallBackCopyBufferLength, - (endOfValueInBuffer - startOfValueInBuffer)); - fallBackCopyBufferLength += (endOfValueInBuffer - startOfValueInBuffer); + if (fallBackCopyBufferLength >= fallBackCopyBuffer.length - length) { // not good at runtime but handled + if (!autoAdjust) { + throw new ArrayIndexOutOfBoundsException("Buffer too small for such a long string"); + } + final char[] newArray = new char[fallBackCopyBuffer.length + Math.max(getBufferExtends(fallBackCopyBuffer.length), length)]; + // TODO: log to adjust size once? + System.arraycopy(fallBackCopyBuffer, 0, newArray, 0, fallBackCopyBufferLength); + System.arraycopy(buffer, startOfValueInBuffer, newArray, fallBackCopyBufferLength, length); + if (releaseFallBackCopyBufferLength) { + bufferProvider.release(fallBackCopyBuffer); + releaseFallBackCopyBufferLength = false; + } + fallBackCopyBuffer = newArray; + } else { + System.arraycopy(buffer, startOfValueInBuffer, fallBackCopyBuffer, fallBackCopyBufferLength, length); + } + fallBackCopyBufferLength += length; } startOfValueInBuffer = endOfValueInBuffer = -1; } + /** + * @return the amount of bytes the current buffer should get extended with + */ + protected int getBufferExtends(int currentLength) { + return currentLength / 4; + } + + @Override public final boolean hasNext() { if (currentStructureElement != null || - (previousEvent != END_ARRAY && previousEvent != END_OBJECT && - previousEvent != VALUE_STRING && previousEvent != VALUE_FALSE && previousEvent != VALUE_TRUE && previousEvent != VALUE_NULL && previousEvent != VALUE_NUMBER) || - previousEvent == 0) { + (previousEvent != END_ARRAY && previousEvent != END_OBJECT && + previousEvent != VALUE_STRING && previousEvent != VALUE_FALSE && previousEvent != VALUE_TRUE && + previousEvent != VALUE_NULL && previousEvent != VALUE_NUMBER) || + previousEvent == 0) { return true; } @@ -317,6 +343,16 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ } @Override + public Event current() { + if (previousEvent < 0 && hasNext()) { + next(); + } + return previousEvent >= 0 && previousEvent < Event.values().length + ? Event.values()[previousEvent] + : null; + } + + @Override public final Event next() { //main entry, make decision how to handle the current character in the stream @@ -324,7 +360,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ throw new NoSuchElementException(); } - if (previousEvent != 0 && currentStructureElement == null) { + if (previousEvent > 0 && currentStructureElement == null) { throw uexc("Unexpected end of structure"); } @@ -415,6 +451,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ } } + protected Event defaultHandling(char c) { if (c == EOF) { throw uexc("End of file hit too early"); @@ -425,7 +462,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ private Event handleStartObject() { //last event must one of the following-> : , [ - if (previousEvent != 0 && previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { + if (previousEvent > 0 && previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { throw uexc("Expected : , ["); } @@ -433,7 +470,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ if (currentStructureElement == null) { currentStructureElement = new StructureElement(null, false); } else { - if(!currentStructureElement.isArray && previousEvent != KEY_SEPARATOR_EVENT) { + if (!currentStructureElement.isArray && previousEvent != KEY_SEPARATOR_EVENT) { throw uexc("Expected :"); } final StructureElement localStructureElement = new StructureElement(currentStructureElement, false); @@ -465,7 +502,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ private Event handleStartArray() { //last event must one of the following-> : , [ - if (previousEvent != 0 && previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { + if (previousEvent > 0 && previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { throw uexc("Expected : , ["); } @@ -473,13 +510,15 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ if (currentStructureElement == null) { currentStructureElement = new StructureElement(null, true); } else { - if(!currentStructureElement.isArray && previousEvent != KEY_SEPARATOR_EVENT) { + if (!currentStructureElement.isArray && previousEvent != KEY_SEPARATOR_EVENT) { throw uexc("Expected \""); } final StructureElement localStructureElement = new StructureElement(currentStructureElement, true); currentStructureElement = localStructureElement; } + arrayDepth++; + return EVT_MAP[previousEvent = START_ARRAY]; } @@ -498,9 +537,16 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //pop from stack currentStructureElement = currentStructureElement.previous; + arrayDepth--; + return EVT_MAP[previousEvent = END_ARRAY]; } + @Override + protected boolean isInArray() { + return arrayDepth > 0; + } + //read a string, gets called recursively //Handles escape/d characters //if string contains escape chars and/or cross buffer boundary then copy in the value buffer @@ -577,7 +623,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ bufferPos--; //unread one char } - } while (true); + } while (true); // before this do while(true) it was: // @@ -630,8 +676,8 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ //always the beginning quote of a key or value //last event must one of the following-> : { [ , - if (previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_OBJECT && previousEvent != START_ARRAY - && previousEvent != COMMA_EVENT) { + if (previousEvent != -1 && (previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_OBJECT && previousEvent != START_ARRAY + && previousEvent != COMMA_EVENT)) { throw uexc("Expected : { [ ,"); } //starting quote already consumed @@ -775,7 +821,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ private Event handleLiteral() { //last event must one of the following-> : , [ - if (previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { + if (previousEvent != -1 && previousEvent != KEY_SEPARATOR_EVENT && previousEvent != START_ARRAY && previousEvent != COMMA_EVENT) { throw uexc("Expected : , ["); } @@ -839,6 +885,11 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ } @Override + public boolean isNotTooLong() { + return (endOfValueInBuffer - startOfValueInBuffer) < 19; + } + + @Override public int getInt() { if (previousEvent != VALUE_NUMBER) { throw new IllegalStateException(EVT_MAP[previousEvent] + " doesn't support getInt()"); @@ -914,7 +965,9 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{ @Override public void close() { bufferProvider.release(buffer); - valueProvider.release(fallBackCopyBuffer); + if (releaseFallBackCopyBufferLength) { + valueProvider.release(fallBackCopyBuffer); + } try { in.close(); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/JsonWriterImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonWriterImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonWriterImpl.java index e012ae1..845ca70 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonWriterImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonWriterImpl.java @@ -18,15 +18,14 @@ */ package org.apache.johnzon.core; -import java.io.Serializable; - import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonStructure; import javax.json.JsonWriter; import javax.json.stream.JsonGenerator; +import java.io.Serializable; -class JsonWriterImpl implements JsonWriter, Serializable{ +class JsonWriterImpl implements JsonWriter, Serializable { private final JsonGenerator generator; private boolean closed = false; @@ -37,37 +36,46 @@ class JsonWriterImpl implements JsonWriter, Serializable{ @Override public void writeArray(final JsonArray array) { checkClosed(); - generator.write(array); - close(); + try { + generator.write(array); + } finally { + close(); + } } @Override public void writeObject(final JsonObject object) { checkClosed(); - generator.write(object); - close(); + try { + generator.write(object); + } finally { + close(); + } } @Override public void write(final JsonStructure value) { checkClosed(); - generator.write(value); - close(); + try { + generator.write(value); + } finally { + close(); + } } @Override public void close() { - - if(!closed) { + + if (!closed) { closed = true; generator.close(); } } - + private void checkClosed() { - if(closed) { + if (closed) { throw new IllegalStateException("writeArray(), writeObject(), write() or close() method was already called"); } - + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/RFC4627AwareInputStreamReader.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/RFC4627AwareInputStreamReader.java b/johnzon-core/src/main/java/org/apache/johnzon/core/RFC4627AwareInputStreamReader.java index 645cf0e..aa09804 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/RFC4627AwareInputStreamReader.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/RFC4627AwareInputStreamReader.java @@ -23,18 +23,21 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PushbackInputStream; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import javax.json.JsonException; final class RFC4627AwareInputStreamReader extends InputStreamReader { - RFC4627AwareInputStreamReader(final InputStream in) { - this(new PushbackInputStream(in,4)); + /** + * @param preferredCharset the Charset to use if no BOM is used. If {@code null} use UTF-8 + */ + RFC4627AwareInputStreamReader(final InputStream in, Charset preferredCharset) { + this(new PushbackInputStream(in,4), preferredCharset); } - - private RFC4627AwareInputStreamReader(final PushbackInputStream in) { - super(in, getCharset(in).newDecoder()); - + + private RFC4627AwareInputStreamReader(final PushbackInputStream in, Charset preferredCharset) { + super(in, getCharset(in, preferredCharset).newDecoder()); } /** @@ -44,10 +47,15 @@ final class RFC4627AwareInputStreamReader extends InputStreamReader { */ private static byte[] readAllBytes(final PushbackInputStream inputStream) throws IOException { final int first = inputStream.read(); + if(first == -1) { + return new byte[0]; + } + final int second = inputStream.read(); - if(first == -1|| second == -1) { - throw new JsonException("Invalid Json. Valid Json has at least 2 bytes"); + if(second == -1) { + return new byte[] {(byte) first}; } + final int third = inputStream.read(); final int fourth = inputStream.read(); if(third == -1) { @@ -78,11 +86,19 @@ final class RFC4627AwareInputStreamReader extends InputStreamReader { */ - private static Charset getCharset(final PushbackInputStream inputStream) { - Charset charset = Charset.forName("UTF-8"); + private static Charset getCharset(final PushbackInputStream inputStream, Charset preferredCharset) { + Charset charset = preferredCharset != null ? preferredCharset : Charset.forName("UTF-8"); int bomLength=0; try { final byte[] utfBytes = readAllBytes(inputStream); + if (utfBytes.length == 0) { + return StandardCharsets.UTF_8; // empty file -> doesn't matter anyway + } + if (utfBytes.length == 1) { + inputStream.unread(utfBytes); + return StandardCharsets.UTF_8; // almost empty file -> doesn't matter neither + } + int first = (utfBytes[0] & 0xFF); int second = (utfBytes[1] & 0xFF); if (first == 0x00) { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/main/java/org/apache/johnzon/core/SimpleStack.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/SimpleStack.java b/johnzon-core/src/main/java/org/apache/johnzon/core/SimpleStack.java index e72540c..74bd14f 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/SimpleStack.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/SimpleStack.java @@ -53,8 +53,8 @@ class SimpleStack<T> { } - Element<T> previous; - T payload; + private Element<T> previous; + private T payload; } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/BrokenDefaultTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/BrokenDefaultTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/BrokenDefaultTest.java new file mode 100644 index 0000000..3ba336e --- /dev/null +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/BrokenDefaultTest.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.johnzon.core; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Queue; + +import javax.json.Json; +import javax.json.stream.JsonParser; +import javax.json.stream.JsonParserFactory; + +import org.junit.Ignore; +import org.junit.Test; + +public class BrokenDefaultTest { + + @Test + @Ignore("buggy but pushing to share the use case") + public void run() throws NoSuchFieldException, IllegalAccessException, UnsupportedEncodingException { // shouldnt fail by default + final JsonParserFactory factory = Json.createParserFactory(Collections.EMPTY_MAP); + final int length = 1024 * 1024; + assertEquals(0, get(Queue.class, get( + BufferStrategy.BufferProvider.class, factory, "bufferProvider"), "queue").size()); + + final JsonParser parser = factory.createParser(newDynamicInput(length)); + + try { + int eventCount = 0; + while (parser.hasNext()) { + eventCount++; + final JsonParser.Event next = parser.next(); + if (eventCount == 2 && next == JsonParser.Event.VALUE_STRING) { + assertEquals(length, parser.getString().length()); + } + } + } finally { + parser.close(); + } + + assertEquals(1, get(Queue.class, get( + BufferStrategy.BufferProvider.class, factory, "bufferProvider"), "queue").size()); + } + + private <T> T get(final Class<T> returnType, final Object instance, final String field) + throws NoSuchFieldException, IllegalAccessException { + Class<?> current = instance.getClass(); + while (current != Object.class) { + try { + final Field declaredField = current.getDeclaredField(field); + if (!declaredField.isAccessible()) { + declaredField.setAccessible(true); + } + return returnType.cast(declaredField.get(instance)); + } catch (final NoSuchFieldException nsfe) { + current = current.getSuperclass(); + } + } + throw new IllegalAccessError(instance + " field: " + field); + } + + private InputStream newDynamicInput(final int size) throws UnsupportedEncodingException { + return new InputStream() { + + private InputStream before = new ByteArrayInputStream("{\"key\":\"".getBytes("UTF-8")); + + private InputStream after = new ByteArrayInputStream("\"}".getBytes("UTF-8")); + + private int remaining = size; + + @Override + public int read() throws IOException { + { + final int val = before.read(); + if (val >= 0) { + return val; + } + } + if (remaining < 0) { + return after.read(); + } + remaining--; + return 'a'; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayBuilderImplTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayBuilderImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayBuilderImplTest.java index df7a1af..9bfd2df 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayBuilderImplTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayBuilderImplTest.java @@ -167,4 +167,5 @@ public class JsonArrayBuilderImplTest { final JsonArrayBuilder builder = Json.createArrayBuilder(); builder.add((double) Double.NEGATIVE_INFINITY); } + } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayImplTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayImplTest.java index b0918b1..8b6dac7 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayImplTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonArrayImplTest.java @@ -58,4 +58,12 @@ public class JsonArrayImplTest { assertTrue(array.isEmpty()); assertEquals("[]", array.toString()); } + + @Test + public void equals() { + assertTrue(Json.createArrayBuilder().build().equals(Json.createArrayBuilder().build())); + assertTrue(Json.createArrayBuilder().add(1).build().equals(Json.createArrayBuilder().add(1).build())); + assertFalse(Json.createArrayBuilder().add(1).build().equals(Json.createArrayBuilder().add(2).build())); + assertFalse(Json.createArrayBuilder().add(1).build().equals(Json.createArrayBuilder().build())); + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonBuilderFactoryTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonBuilderFactoryTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonBuilderFactoryTest.java new file mode 100644 index 0000000..f897e70 --- /dev/null +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonBuilderFactoryTest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.johnzon.core; + +import java.util.Collections; + +import javax.json.Json; +import javax.json.JsonBuilderFactory; +import javax.json.JsonObject; + +import org.junit.Assert; +import org.junit.Test; + + +public class JsonBuilderFactoryTest { + + @Test + public void testCreateBuilderFactory() { + JsonBuilderFactory factory = Json.createBuilderFactory(Collections.EMPTY_MAP); + JsonObject jsonObject = factory.createObjectBuilder(). + add("name", "home"). + add("city", "Vienna") + .build(); + + //JsonObject + Assert.assertEquals("home", jsonObject.getString("name")); + Assert.assertEquals("Vienna", jsonObject.getString("city")); + + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java index 797cca5..83561c6 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java @@ -18,6 +18,7 @@ */ package org.apache.johnzon.core; +import org.junit.Assert; import org.junit.Test; import javax.json.Json; @@ -50,6 +51,19 @@ public class JsonGeneratorImplTest { } @Test + public void testCreateGenerator() { + StringWriter sw = new StringWriter(); + JsonGenerator jsonGenerator = Json.createGenerator(sw); + jsonGenerator.writeStartObject() + .write("a", "b") + .write("c", "d") + .writeEnd(); + + jsonGenerator.close(); + + Assert.assertEquals("{\"a\":\"b\",\"c\":\"d\"}", sw.toString()); + } + @Test public void emptyArray() { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final JsonGenerator generator = Json.createGenerator(baos);
