diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java index 2a95b69a..b2e0dfef 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java @@ -33,6 +33,7 @@ import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePack; import org.msgpack.core.MessageUnpacker; +import org.msgpack.core.annotations.Nullable; import org.msgpack.core.buffer.ArrayBufferInput; import org.msgpack.core.buffer.InputStreamBufferInput; import org.msgpack.core.buffer.MessageBufferInput; @@ -47,8 +48,8 @@ public class MessagePackParser extends ParserMinimalBase { - private static final ThreadLocal> messageUnpackerHolder = - new ThreadLocal>(); + private static final ThreadLocal> reuseObjectHolder = + new ThreadLocal<>(); private final MessageUnpacker messageUnpacker; private static final BigInteger LONG_MIN = BigInteger.valueOf((long) Long.MIN_VALUE); @@ -130,7 +131,7 @@ public MessagePackParser( boolean reuseResourceInParser) throws IOException { - this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in, reuseResourceInParser); + this(ctxt, features, null, in, objectCodec, in, reuseResourceInParser); } public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, byte[] bytes) @@ -147,12 +148,53 @@ public MessagePackParser( boolean reuseResourceInParser) throws IOException { - this(ctxt, features, new ArrayBufferInput(bytes), objectCodec, bytes, reuseResourceInParser); + this(ctxt, features, bytes, null, objectCodec, bytes, reuseResourceInParser); + } + + private MessageBufferInput createMessageBufferInput( + // Either of `bytes` or `in` is available + @Nullable byte[] bytes, + @Nullable InputStream in) + { + if (bytes != null) { + return new ArrayBufferInput(bytes); + } + else if (in != null) { + return new InputStreamBufferInput(in); + } + else { + throw new IllegalArgumentException("The both `bytes` and `in` are null"); + } + } + + private MessageBufferInput resetOrRecreateMessageBufferInput( + MessageBufferInput messageBufferInput, + // Either of `bytes` or `in` is available + @Nullable byte[] bytes, + @Nullable InputStream in) + throws IOException + { + // TODO: Revisit here + messageBufferInput.close(); + if (messageBufferInput instanceof ArrayBufferInput && bytes != null) { + ((ArrayBufferInput) messageBufferInput).reset(bytes); + } + else if (messageBufferInput instanceof InputStreamBufferInput && in != null) { + ((InputStreamBufferInput) messageBufferInput).reset(in); + } + else { + // The existing MessageBufferInput type doesn't match the new source type. + // Recreate MessageBufferInput instance. + return createMessageBufferInput(bytes, in); + } + return messageBufferInput; } private MessagePackParser(IOContext ctxt, int features, - MessageBufferInput input, + // Either of `bytes` or `in` is available + @Nullable byte[] bytes, + @Nullable InputStream in, ObjectCodec objectCodec, Object src, boolean reuseResourceInParser) @@ -167,7 +209,7 @@ private MessagePackParser(IOContext ctxt, parsingContext = JsonReadContext.createRootContext(dups); this.reuseResourceInParser = reuseResourceInParser; if (!reuseResourceInParser) { - this.messageUnpacker = MessagePack.newDefaultUnpacker(input); + this.messageUnpacker = MessagePack.newDefaultUnpacker(createMessageBufferInput(bytes, in)); return; } else { @@ -175,21 +217,30 @@ private MessagePackParser(IOContext ctxt, } MessageUnpacker messageUnpacker; - Tuple messageUnpackerTuple = messageUnpackerHolder.get(); - if (messageUnpackerTuple == null) { - messageUnpacker = MessagePack.newDefaultUnpacker(input); + MessageBufferInput messageBufferInput; + Triple messageUnpackerResource = reuseObjectHolder.get(); + if (messageUnpackerResource == null) { + messageBufferInput = createMessageBufferInput(bytes, in); + messageUnpacker = MessagePack.newDefaultUnpacker(messageBufferInput); } else { // Considering to reuse InputStream with JsonParser.Feature.AUTO_CLOSE_SOURCE, // MessagePackParser needs to use the MessageUnpacker that has the same InputStream // since it has buffer which has loaded the InputStream data ahead. // However, it needs to call MessageUnpacker#reset when the source is different from the previous one. - if (isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE) || messageUnpackerTuple.first() != src) { - messageUnpackerTuple.second().reset(input); + if (isEnabled(Feature.AUTO_CLOSE_SOURCE) || messageUnpackerResource.first() != src) { + messageBufferInput = messageUnpackerResource.third(); + messageUnpacker = messageUnpackerResource.second(); + + messageBufferInput = resetOrRecreateMessageBufferInput(messageBufferInput, bytes, in); + messageUnpacker.reset(messageBufferInput); + } + else { + messageBufferInput = messageUnpackerResource.third(); + messageUnpacker = messageUnpackerResource.second(); } - messageUnpacker = messageUnpackerTuple.second(); } - messageUnpackerHolder.set(new Tuple(src, messageUnpacker)); + reuseObjectHolder.set(new Triple<>(src, messageUnpacker, messageBufferInput)); } public void setExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers extTypeCustomDesers) @@ -690,10 +741,10 @@ private MessageUnpacker getMessageUnpacker() return this.messageUnpacker; } - Tuple messageUnpackerTuple = messageUnpackerHolder.get(); - if (messageUnpackerTuple == null) { + Triple reuseObject = reuseObjectHolder.get(); + if (reuseObject == null) { throw new IllegalStateException("messageUnpacker is null"); } - return messageUnpackerTuple.second(); + return reuseObject.second(); } } diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Triple.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Triple.java new file mode 100644 index 00000000..3f35b467 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Triple.java @@ -0,0 +1,45 @@ +// +// MessagePack for Java +// +// Licensed 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.msgpack.jackson.dataformat; + +public class Triple +{ + private final F first; + private final S second; + private final T third; + + public Triple(F first, S second, T third) + { + this.first = first; + this.second = second; + this.third = third; + } + + public F first() + { + return first; + } + + public S second() + { + return second; + } + + public T third() + { + return third; + } +} diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Tuple.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Tuple.java index 1a252739..b0f720d8 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Tuple.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/Tuple.java @@ -15,9 +15,6 @@ // package org.msgpack.jackson.dataformat; -/** - * Created by komamitsu on 5/28/15. - */ public class Tuple { private final F first;