View Javadoc

    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 org.jboss.netty.handler.codec.marshalling;
    17
    18  import java.io.StreamCorruptedException;
    19
    20  import org.jboss.marshalling.ByteInput;
    21  import org.jboss.marshalling.Unmarshaller;
    22  import org.jboss.netty.buffer.ChannelBuffer;
    23  import org.jboss.netty.channel.Channel;
    24  import org.jboss.netty.channel.ChannelHandlerContext;
    25  import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
    26  import org.jboss.netty.handler.codec.frame.TooLongFrameException;
    27  /**
    28   * Decoder which MUST be used with {@link MarshallingEncoder}.
    29   *
    30   * A {@link LengthFieldBasedFrameDecoder} which use an {@link Unmarshaller} to read the Object out
    31   * of the {@link ChannelBuffer}.
    32   *
    33   */
    34  public class MarshallingDecoder extends LengthFieldBasedFrameDecoder {
    35
    36      private final UnmarshallerProvider provider;
    37
    38      /**
    39       * Creates a new decoder whose maximum object size is {@code 1048576}
    40       * bytes.  If the size of the received object is greater than
    41       * {@code 1048576} bytes, a {@link StreamCorruptedException} will be
    42       * raised.
    43       *
    44       */
    45      public MarshallingDecoder(UnmarshallerProvider provider) {
    46          this(provider, 1048576);
    47      }
    48
    49      /**
    50       * Creates a new decoder with the specified maximum object size.
    51       *
    52       * @param maxObjectSize  the maximum byte length of the serialized object.
    53       *                       if the length of the received object is greater
    54       *                       than this value, {@link TooLongFrameException}
    55       *                       will be raised.
    56       */
    57      public MarshallingDecoder(UnmarshallerProvider provider, int maxObjectSize) {
    58          super(maxObjectSize, 0, 4, 0, 4);
    59          this.provider = provider;
    60      }
    61
    62
    63      @Override
    64      protected Object decode(
    65              ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
    66
    67          ChannelBuffer frame = (ChannelBuffer) super.decode(ctx, channel, buffer);
    68          if (frame == null) {
    69              return null;
    70          }
    71
    72          Unmarshaller unmarshaller = provider.getUnmarshaller(ctx);
    73          ByteInput input = new ChannelBufferByteInput(frame);
    74
    75          try {
    76              unmarshaller.start(input);
    77              Object obj = unmarshaller.readObject();
    78              unmarshaller.finish();
    79              return obj;
    80          } finally {
    81              // Call close in a finally block as the ReplayingDecoder will throw an Error if not
    82              // enough bytes are readable. This helps to be sure that we do not leak resource
    83              unmarshaller.close();
    84          }
    85      }
    86
    87      @Override
    88      protected ChannelBuffer extractFrame(ChannelBuffer buffer, int index, int length) {
    89          return buffer.slice(index, length);
    90      }
    91  }