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.serialization;
    17
    18  import java.io.InputStream;
    19  import java.io.ObjectInputStream;
    20  import java.io.ObjectOutputStream;
    21  import java.io.ObjectStreamConstants;
    22
    23  import org.jboss.netty.buffer.ChannelBuffer;
    24  import org.jboss.netty.buffer.ChannelBufferInputStream;
    25  import org.jboss.netty.channel.Channel;
    26  import org.jboss.netty.channel.ChannelHandlerContext;
    27  import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
    28
    29  /**
    30   * A decoder which deserializes the received {@link ChannelBuffer}s into Java
    31   * objects (interoperability version).
    32   * <p>
    33   * This decoder is interoperable with the standard Java object
    34   * streams such as {@link ObjectInputStream} and {@link ObjectOutputStream}.
    35   * <p>
    36   * However, this decoder might perform worse than {@link ObjectDecoder} if
    37   * the serialized object is big and complex.  Also, it does not limit the
    38   * maximum size of the object, and consequently your application might face
    39   * the risk of <a href="http://en.wikipedia.org/wiki/DoS">DoS attack</a>.
    40   * Please use {@link ObjectEncoder} and {@link ObjectDecoder} if you are not
    41   * required to keep the interoperability with the standard object streams.
    42   *
    43   * @deprecated This decoder has a known critical bug which fails to decode and
    44   *             raises a random exception in some circumstances.  Avoid to use
    45   *             it whenever you can. The only workaround is to replace
    46   *             {@link CompatibleObjectEncoder}, {@link CompatibleObjectDecoder},
    47   *             {@link ObjectInputStream}, and {@link ObjectOutputStream} with
    48   *             {@link ObjectEncoder}, {@link ObjectDecoder},
    49   *             {@link ObjectEncoderOutputStream}, and
    50   *             {@link ObjectDecoderInputStream} respectively.  This workaround
    51   *             requires both a client and a server to be modified.
    52   */
    53  @Deprecated
    54  public class CompatibleObjectDecoder extends ReplayingDecoder<CompatibleObjectDecoderState> {
    55
    56      private final SwitchableInputStream bin = new SwitchableInputStream();
    57      private ObjectInputStream oin;
    58
    59      /**
    60       * Creates a new decoder.
    61       */
    62      public CompatibleObjectDecoder() {
    63          super(CompatibleObjectDecoderState.READ_HEADER);
    64      }
    65
    66      /**
    67       * Creates a new {@link ObjectInputStream} which wraps the specified
    68       * {@link InputStream}.  Override this method to use a subclass of the
    69       * {@link ObjectInputStream}.
    70       */
    71      protected ObjectInputStream newObjectInputStream(InputStream in) throws Exception {
    72          return new ObjectInputStream(in);
    73      }
    74
    75      @Override
    76      protected Object decode(
    77              ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer,
    78              CompatibleObjectDecoderState state) throws Exception {
    79          bin.switchStream(new ChannelBufferInputStream(buffer));
    80          switch (state) {
    81          case READ_HEADER:
    82              oin = newObjectInputStream(bin);
    83              checkpoint(CompatibleObjectDecoderState.READ_OBJECT);
    84          case READ_OBJECT:
    85              return oin.readObject();
    86          default:
    87              throw new IllegalStateException("Unknown state: " + state);
    88          }
    89      }
    90
    91      @Override
    92      protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
    93              ChannelBuffer buffer, CompatibleObjectDecoderState state)
    94              throws Exception {
    95          switch (buffer.readableBytes()) {
    96          case 0:
    97              return null;
    98          case 1:
    99              // Ignore the last TC_RESET
    100             if (buffer.getByte(buffer.readerIndex()) == ObjectStreamConstants.TC_RESET) {
    101                 buffer.skipBytes(1);
    102                 oin.close();
    103                 return null;
    104             }
    105         }
    106
    107         Object decoded =  decode(ctx, channel, buffer, state);
    108         oin.close();
    109         return decoded;
    110     }
    111 }