1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec;
17
18 import io.netty.channel.ChannelHandlerContext;
19 import io.netty.channel.ChannelInboundHandler;
20 import io.netty.channel.ChannelInboundHandlerAdapter;
21 import io.netty.channel.ChannelPipeline;
22 import io.netty.util.ReferenceCountUtil;
23 import io.netty.util.ReferenceCounted;
24 import io.netty.util.internal.TypeParameterMatcher;
25
26 import java.util.List;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public abstract class MessageToMessageDecoder<I> extends ChannelInboundHandlerAdapter {
53
54 private final TypeParameterMatcher matcher;
55 private boolean decodeCalled;
56 private boolean messageProduced;
57
58
59
60
61 protected MessageToMessageDecoder() {
62 matcher = TypeParameterMatcher.find(this, MessageToMessageDecoder.class, "I");
63 }
64
65
66
67
68
69
70 protected MessageToMessageDecoder(Class<? extends I> inboundMessageType) {
71 matcher = TypeParameterMatcher.get(inboundMessageType);
72 }
73
74
75
76
77
78 public boolean acceptInboundMessage(Object msg) throws Exception {
79 return matcher.match(msg);
80 }
81
82 @Override
83 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
84 decodeCalled = true;
85 CodecOutputList out = CodecOutputList.newInstance();
86 try {
87 if (acceptInboundMessage(msg)) {
88 @SuppressWarnings("unchecked")
89 I cast = (I) msg;
90 try {
91 decode(ctx, cast, out);
92 } finally {
93 ReferenceCountUtil.release(cast);
94 }
95 } else {
96 out.add(msg);
97 }
98 } catch (DecoderException e) {
99 throw e;
100 } catch (Exception e) {
101 throw new DecoderException(e);
102 } finally {
103 try {
104 int size = out.size();
105 messageProduced |= size > 0;
106 for (int i = 0; i < size; i++) {
107 ctx.fireChannelRead(out.getUnsafe(i));
108 }
109 } finally {
110 out.recycle();
111 }
112 }
113 }
114
115 @Override
116 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
117 if (!isSharable()) {
118
119 if (decodeCalled && !messageProduced && !ctx.channel().config().isAutoRead()) {
120 ctx.read();
121 }
122 decodeCalled = false;
123 messageProduced = false;
124 }
125 ctx.fireChannelReadComplete();
126 }
127
128
129
130
131
132
133
134
135
136
137 protected abstract void decode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;
138 }