1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.marshalling;
17
18 import org.jboss.marshalling.ByteInput;
19 import org.jboss.marshalling.Unmarshaller;
20 import org.jboss.netty.buffer.ChannelBuffer;
21 import org.jboss.netty.channel.Channel;
22 import org.jboss.netty.channel.ChannelHandlerContext;
23 import org.jboss.netty.channel.ExceptionEvent;
24 import org.jboss.netty.handler.codec.frame.TooLongFrameException;
25 import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
26 import org.jboss.netty.handler.codec.replay.VoidEnum;
27
28 import java.io.ObjectStreamConstants;
29
30
31
32
33
34
35
36
37
38 public class CompatibleMarshallingDecoder extends ReplayingDecoder<VoidEnum> {
39 protected final UnmarshallerProvider provider;
40 protected final int maxObjectSize;
41 private boolean discardingTooLongFrame;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public CompatibleMarshallingDecoder(UnmarshallerProvider provider, int maxObjectSize) {
57 this.provider = provider;
58 this.maxObjectSize = maxObjectSize;
59 }
60
61 @Override
62 protected Object decode(
63 ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, VoidEnum state) throws Exception {
64 if (discardingTooLongFrame) {
65 buffer.skipBytes(actualReadableBytes());
66 checkpoint();
67 return null;
68 }
69
70 Unmarshaller unmarshaller = provider.getUnmarshaller(ctx);
71 ByteInput input = new ChannelBufferByteInput(buffer);
72 if (maxObjectSize != Integer.MAX_VALUE) {
73 input = new LimitingByteInput(input, maxObjectSize);
74 }
75 try {
76 unmarshaller.start(input);
77 Object obj = unmarshaller.readObject();
78 unmarshaller.finish();
79 return obj;
80 } catch (LimitingByteInput.TooBigObjectException e) {
81 discardingTooLongFrame = true;
82 throw new TooLongFrameException();
83 } finally {
84
85
86 unmarshaller.close();
87 }
88 }
89
90 @Override
91 protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
92 ChannelBuffer buffer, VoidEnum state)
93 throws Exception {
94 switch (buffer.readableBytes()) {
95 case 0:
96 return null;
97 case 1:
98
99 if (buffer.getByte(buffer.readerIndex()) == ObjectStreamConstants.TC_RESET) {
100 buffer.skipBytes(1);
101 return null;
102 }
103 }
104
105 Object decoded = decode(ctx, channel, buffer, state);
106 return decoded;
107 }
108
109
110
111
112 @Override
113 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
114 if (e.getCause() instanceof TooLongFrameException) {
115 e.getChannel().close();
116 } else {
117 super.exceptionCaught(ctx, e);
118 }
119 }
120 }