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.buffer.ByteBuf;
19 import io.netty.channel.ChannelDuplexHandler;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.channel.ChannelPromise;
22 import io.netty.util.internal.TypeParameterMatcher;
23
24 import java.util.List;
25
26
27
28
29
30
31
32
33
34 public abstract class ByteToMessageCodec<I> extends ChannelDuplexHandler {
35
36 private final TypeParameterMatcher outboundMsgMatcher;
37 private final MessageToByteEncoder<I> encoder;
38
39 private final ByteToMessageDecoder decoder = new ByteToMessageDecoder() {
40 @Override
41 public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
42 ByteToMessageCodec.this.decode(ctx, in, out);
43 }
44
45 @Override
46 protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
47 ByteToMessageCodec.this.decodeLast(ctx, in, out);
48 }
49 };
50
51
52
53
54 protected ByteToMessageCodec() {
55 this(true);
56 }
57
58
59
60
61 protected ByteToMessageCodec(Class<? extends I> outboundMessageType) {
62 this(outboundMessageType, true);
63 }
64
65
66
67
68
69
70
71
72 protected ByteToMessageCodec(boolean preferDirect) {
73 ensureNotSharable();
74 outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I");
75 encoder = new Encoder(preferDirect);
76 }
77
78
79
80
81
82
83
84
85
86 protected ByteToMessageCodec(Class<? extends I> outboundMessageType, boolean preferDirect) {
87 ensureNotSharable();
88 outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType);
89 encoder = new Encoder(preferDirect);
90 }
91
92
93
94
95
96
97 public boolean acceptOutboundMessage(Object msg) throws Exception {
98 return outboundMsgMatcher.match(msg);
99 }
100
101 @Override
102 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
103 decoder.channelRead(ctx, msg);
104 }
105
106 @Override
107 public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
108 encoder.write(ctx, msg, promise);
109 }
110
111 @Override
112 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
113 decoder.channelReadComplete(ctx);
114 }
115
116 @Override
117 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
118 decoder.channelInactive(ctx);
119 }
120
121 @Override
122 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
123 try {
124 decoder.handlerAdded(ctx);
125 } finally {
126 encoder.handlerAdded(ctx);
127 }
128 }
129
130 @Override
131 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
132 try {
133 decoder.handlerRemoved(ctx);
134 } finally {
135 encoder.handlerRemoved(ctx);
136 }
137 }
138
139
140
141
142 protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
143
144
145
146
147 protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;
148
149
150
151
152 protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
153 if (in.isReadable()) {
154
155
156 decode(ctx, in, out);
157 }
158 }
159
160 private final class Encoder extends MessageToByteEncoder<I> {
161 Encoder(boolean preferDirect) {
162 super(preferDirect);
163 }
164
165 @Override
166 public boolean acceptOutboundMessage(Object msg) throws Exception {
167 return ByteToMessageCodec.this.acceptOutboundMessage(msg);
168 }
169
170 @Override
171 protected void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception {
172 ByteToMessageCodec.this.encode(ctx, msg, out);
173 }
174 }
175 }