Skip to content

Commit 347b5e5

Browse files
authored
Merge pull request #408 from msgpack/jackson-typebase-ext-deser
Jackson typebase ext deser
2 parents 7f49d93 + 473268e commit 347b5e5

File tree

5 files changed

+283
-6
lines changed

5 files changed

+283
-6
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// MessagePack for Java
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
package org.msgpack.jackson.dataformat;
17+
18+
import com.fasterxml.jackson.core.type.TypeReference;
19+
import com.fasterxml.jackson.databind.ObjectMapper;
20+
21+
import java.io.IOException;
22+
import java.util.Map;
23+
import java.util.concurrent.ConcurrentHashMap;
24+
25+
public class ExtensionTypeCustomDeserializers
26+
{
27+
private final ObjectMapper objectMapper;
28+
private Map<Byte, Deser> deserTable = new ConcurrentHashMap<Byte, Deser>();
29+
30+
public ExtensionTypeCustomDeserializers()
31+
{
32+
objectMapper = new ObjectMapper(new MessagePackFactory().setReuseResourceInParser(false));
33+
}
34+
35+
public <T> void addTargetClass(byte type, final Class<T> klass)
36+
{
37+
deserTable.put(type, new Deser()
38+
{
39+
@Override
40+
public Object deserialize(byte[] data)
41+
throws IOException
42+
{
43+
return objectMapper.readValue(data, klass);
44+
}
45+
});
46+
}
47+
48+
public void addTargetTypeReference(byte type, final TypeReference typeReference)
49+
{
50+
deserTable.put(type, new Deser()
51+
{
52+
@Override
53+
public Object deserialize(byte[] data)
54+
throws IOException
55+
{
56+
return objectMapper.readValue(data, typeReference);
57+
}
58+
});
59+
}
60+
61+
public void addCustomDeser(byte type, final Deser deser)
62+
{
63+
deserTable.put(type, new Deser()
64+
{
65+
@Override
66+
public Object deserialize(byte[] data)
67+
throws IOException
68+
{
69+
return deser.deserialize(data);
70+
}
71+
});
72+
}
73+
74+
public Deser getDeser(byte type)
75+
{
76+
return deserTable.get(type);
77+
}
78+
79+
public void clearEntries()
80+
{
81+
deserTable.clear();
82+
}
83+
84+
public interface Deser
85+
{
86+
Object deserialize(byte[] data)
87+
throws IOException;
88+
}
89+
}

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackExtensionType.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
88

99
import java.io.IOException;
10+
import java.util.Arrays;
1011

1112
@JsonSerialize(using = MessagePackExtensionType.Serializer.class)
1213
public class MessagePackExtensionType
@@ -30,6 +31,32 @@ public byte[] getData()
3031
return data;
3132
}
3233

34+
@Override
35+
public boolean equals(Object o)
36+
{
37+
if (this == o) {
38+
return true;
39+
}
40+
if (!(o instanceof MessagePackExtensionType)) {
41+
return false;
42+
}
43+
44+
MessagePackExtensionType that = (MessagePackExtensionType) o;
45+
46+
if (type != that.type) {
47+
return false;
48+
}
49+
return Arrays.equals(data, that.data);
50+
}
51+
52+
@Override
53+
public int hashCode()
54+
{
55+
int result = (int) type;
56+
result = 31 * result + Arrays.hashCode(data);
57+
return result;
58+
}
59+
3360
public static class Serializer extends JsonSerializer<MessagePackExtensionType>
3461
{
3562
@Override

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackFactory.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class MessagePackFactory
3838

3939
private final MessagePack.PackerConfig packerConfig;
4040
private boolean reuseResourceInGenerator = true;
41+
private boolean reuseResourceInParser = true;
42+
private ExtensionTypeCustomDeserializers extTypeCustomDesers;
4143

4244
public MessagePackFactory()
4345
{
@@ -49,9 +51,22 @@ public MessagePackFactory(MessagePack.PackerConfig packerConfig)
4951
this.packerConfig = packerConfig;
5052
}
5153

52-
public void setReuseResourceInGenerator(boolean reuseResourceInGenerator)
54+
public MessagePackFactory setReuseResourceInGenerator(boolean reuseResourceInGenerator)
5355
{
5456
this.reuseResourceInGenerator = reuseResourceInGenerator;
57+
return this;
58+
}
59+
60+
public MessagePackFactory setReuseResourceInParser(boolean reuseResourceInParser)
61+
{
62+
this.reuseResourceInParser = reuseResourceInParser;
63+
return this;
64+
}
65+
66+
public MessagePackFactory setExtTypeCustomDesers(ExtensionTypeCustomDeserializers extTypeCustomDesers)
67+
{
68+
this.extTypeCustomDesers = extTypeCustomDesers;
69+
return this;
5570
}
5671

5772
@Override
@@ -95,7 +110,10 @@ public JsonParser createParser(InputStream in)
95110
protected MessagePackParser _createParser(InputStream in, IOContext ctxt)
96111
throws IOException
97112
{
98-
MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, in);
113+
MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, in, reuseResourceInParser);
114+
if (extTypeCustomDesers != null) {
115+
parser.setExtensionTypeCustomDeserializers(extTypeCustomDesers);
116+
}
99117
return parser;
100118
}
101119

@@ -106,7 +124,10 @@ protected JsonParser _createParser(byte[] data, int offset, int len, IOContext c
106124
if (offset != 0 || len != data.length) {
107125
data = Arrays.copyOfRange(data, offset, offset + len);
108126
}
109-
MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, data);
127+
MessagePackParser parser = new MessagePackParser(ctxt, _parserFeatures, _objectCodec, data, reuseResourceInParser);
128+
if (extTypeCustomDesers != null) {
129+
parser.setExtensionTypeCustomDeserializers(extTypeCustomDesers);
130+
}
110131
return parser;
111132
}
112133
}

msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackParser.java

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public class MessagePackParser
4949
{
5050
private static final ThreadLocal<Tuple<Object, MessageUnpacker>> messageUnpackerHolder =
5151
new ThreadLocal<Tuple<Object, MessageUnpacker>>();
52+
private final MessageUnpacker messageUnpacker;
5253

5354
private static final BigInteger LONG_MIN = BigInteger.valueOf((long) Long.MIN_VALUE);
5455
private static final BigInteger LONG_MAX = BigInteger.valueOf((long) Long.MAX_VALUE);
@@ -61,6 +62,7 @@ public class MessagePackParser
6162
private long tokenPosition;
6263
private long currentPosition;
6364
private final IOContext ioContext;
65+
private ExtensionTypeCustomDeserializers extTypeCustomDesers;
6466

6567
private enum Type
6668
{
@@ -74,6 +76,7 @@ private enum Type
7476
private String stringValue;
7577
private BigInteger biValue;
7678
private MessagePackExtensionType extensionTypeValue;
79+
private boolean reuseResourceInParser;
7780

7881
private abstract static class StackItem
7982
{
@@ -116,16 +119,43 @@ private static class StackItemForArray
116119
public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, InputStream in)
117120
throws IOException
118121
{
119-
this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in);
122+
this(ctxt, features, objectCodec, in, true);
123+
}
124+
125+
public MessagePackParser(
126+
IOContext ctxt,
127+
int features,
128+
ObjectCodec objectCodec,
129+
InputStream in,
130+
boolean reuseResourceInParser)
131+
throws IOException
132+
{
133+
this(ctxt, features, new InputStreamBufferInput(in), objectCodec, in, reuseResourceInParser);
120134
}
121135

122136
public MessagePackParser(IOContext ctxt, int features, ObjectCodec objectCodec, byte[] bytes)
123137
throws IOException
124138
{
125-
this(ctxt, features, new ArrayBufferInput(bytes), objectCodec, bytes);
139+
this(ctxt, features, objectCodec, bytes, true);
126140
}
127141

128-
private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input, ObjectCodec objectCodec, Object src)
142+
public MessagePackParser(
143+
IOContext ctxt,
144+
int features,
145+
ObjectCodec objectCodec,
146+
byte[] bytes,
147+
boolean reuseResourceInParser)
148+
throws IOException
149+
{
150+
this(ctxt, features, new ArrayBufferInput(bytes), objectCodec, bytes, reuseResourceInParser);
151+
}
152+
153+
private MessagePackParser(IOContext ctxt,
154+
int features,
155+
MessageBufferInput input,
156+
ObjectCodec objectCodec,
157+
Object src,
158+
boolean reuseResourceInParser)
129159
throws IOException
130160
{
131161
super(features);
@@ -135,6 +165,14 @@ private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input
135165
DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features)
136166
? DupDetector.rootDetector(this) : null;
137167
parsingContext = JsonReadContext.createRootContext(dups);
168+
this.reuseResourceInParser = reuseResourceInParser;
169+
if (!reuseResourceInParser) {
170+
this.messageUnpacker = MessagePack.newDefaultUnpacker(input);
171+
return;
172+
}
173+
else {
174+
this.messageUnpacker = null;
175+
}
138176

139177
MessageUnpacker messageUnpacker;
140178
Tuple<Object, MessageUnpacker> messageUnpackerTuple = messageUnpackerHolder.get();
@@ -154,6 +192,11 @@ private MessagePackParser(IOContext ctxt, int features, MessageBufferInput input
154192
messageUnpackerHolder.set(new Tuple<Object, MessageUnpacker>(src, messageUnpacker));
155193
}
156194

195+
public void setExtensionTypeCustomDeserializers(ExtensionTypeCustomDeserializers extTypeCustomDesers)
196+
{
197+
this.extTypeCustomDesers = extTypeCustomDesers;
198+
}
199+
157200
@Override
158201
public ObjectCodec getCodec()
159202
{
@@ -514,6 +557,12 @@ public Object getEmbeddedObject()
514557
case BYTES:
515558
return bytesValue;
516559
case EXT:
560+
if (extTypeCustomDesers != null) {
561+
ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType());
562+
if (deser != null) {
563+
return deser.deserialize(extensionTypeValue.getData());
564+
}
565+
}
517566
return extensionTypeValue;
518567
default:
519568
throw new IllegalStateException("Invalid type=" + type);
@@ -607,6 +656,10 @@ public String getCurrentName()
607656

608657
private MessageUnpacker getMessageUnpacker()
609658
{
659+
if (!reuseResourceInParser) {
660+
return this.messageUnpacker;
661+
}
662+
610663
Tuple<Object, MessageUnpacker> messageUnpackerTuple = messageUnpackerHolder.get();
611664
if (messageUnpackerTuple == null) {
612665
throw new IllegalStateException("messageUnpacker is null");

0 commit comments

Comments
 (0)