View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * 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   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
54   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
55   *
56   * @version $Rev: 2188 $, $Date: 2010-02-19 18:00:00 +0900 (Fri, 19 Feb 2010) $
57   */
58  @Deprecated
59  public class CompatibleObjectDecoder extends ReplayingDecoder<CompatibleObjectDecoderState> {
60  
61      private final SwitchableInputStream bin = new SwitchableInputStream();
62      private ObjectInputStream oin;
63  
64      /**
65       * Creates a new decoder.
66       */
67      public CompatibleObjectDecoder() {
68          super(CompatibleObjectDecoderState.READ_HEADER);
69      }
70  
71      /**
72       * Creates a new {@link ObjectInputStream} which wraps the specified
73       * {@link InputStream}.  Override this method to use a subclass of the
74       * {@link ObjectInputStream}.
75       */
76      protected ObjectInputStream newObjectInputStream(InputStream in) throws Exception {
77          return new ObjectInputStream(in);
78      }
79  
80      @Override
81      protected Object decode(
82              ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, CompatibleObjectDecoderState state) throws Exception {
83          bin.switchStream(new ChannelBufferInputStream(buffer));
84          switch (state) {
85          case READ_HEADER:
86              oin = newObjectInputStream(bin);
87              checkpoint(CompatibleObjectDecoderState.READ_OBJECT);
88          case READ_OBJECT:
89              return oin.readObject();
90          default:
91              throw new IllegalStateException("Unknown state: " + state);
92          }
93      }
94  
95      @Override
96      protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
97              ChannelBuffer buffer, CompatibleObjectDecoderState state)
98              throws Exception {
99          switch (buffer.readableBytes()) {
100         case 0:
101             return null;
102         case 1:
103             // Ignore the last TC_RESET
104             if (buffer.getByte(buffer.readerIndex()) == ObjectStreamConstants.TC_RESET) {
105                 buffer.skipBytes(1);
106                 oin.close();
107                 return null;
108             }
109         }
110 
111         Object decoded =  decode(ctx, channel, buffer, state);
112         oin.close();
113         return decoded;
114     }
115 }