1 /*
2 * Copyright 2012 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.handler.codec.marshalling;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
21 import io.netty.handler.codec.TooLongFrameException;
22 import org.jboss.marshalling.ByteInput;
23 import org.jboss.marshalling.Unmarshaller;
24
25 import java.io.StreamCorruptedException;
26 /**
27 * Decoder which MUST be used with {@link MarshallingEncoder}.
28 *
29 * A {@link LengthFieldBasedFrameDecoder} which use an {@link Unmarshaller} to read the Object out
30 * of the {@link ByteBuf}.
31 *
32 */
33 public class MarshallingDecoder extends LengthFieldBasedFrameDecoder {
34
35 private final UnmarshallerProvider provider;
36
37 /**
38 * Creates a new decoder whose maximum object size is {@code 1048576}
39 * bytes. If the size of the received object is greater than
40 * {@code 1048576} bytes, a {@link StreamCorruptedException} will be
41 * raised.
42 *
43 */
44 public MarshallingDecoder(UnmarshallerProvider provider) {
45 this(provider, 1048576);
46 }
47
48 /**
49 * Creates a new decoder with the specified maximum object size.
50 *
51 * @param maxObjectSize the maximum byte length of the serialized object.
52 * if the length of the received object is greater
53 * than this value, {@link TooLongFrameException}
54 * will be raised.
55 */
56 public MarshallingDecoder(UnmarshallerProvider provider, int maxObjectSize) {
57 super(maxObjectSize, 0, 4, 0, 4);
58 this.provider = provider;
59 }
60
61 @Override
62 protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
63 ByteBuf frame = (ByteBuf) super.decode(ctx, in);
64 if (frame == null) {
65 return null;
66 }
67
68 Unmarshaller unmarshaller = provider.getUnmarshaller(ctx);
69 ByteInput input = new ChannelBufferByteInput(frame);
70
71 try {
72 unmarshaller.start(input);
73 Object obj = unmarshaller.readObject();
74 unmarshaller.finish();
75 return obj;
76 } finally {
77 // Call close in a finally block as the ReplayingDecoder will throw an Error if not enough bytes are
78 // readable. This helps to be sure that we do not leak resource
79 unmarshaller.close();
80 }
81 }
82
83 @Override
84 protected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) {
85 return buffer.slice(index, length);
86 }
87 }