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 static org.jboss.netty.buffer.ChannelBuffers.*;
19  
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  
23  import org.jboss.netty.buffer.ChannelBuffer;
24  import org.jboss.netty.buffer.ChannelBufferOutputStream;
25  import org.jboss.netty.channel.Channel;
26  import org.jboss.netty.channel.ChannelHandler.Sharable;
27  import org.jboss.netty.channel.ChannelHandlerContext;
28  import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
29  
30  /**
31   * An encoder which serializes a Java object into a {@link ChannelBuffer}.
32   * <p>
33   * Please note that the serialized form this encoder produces is not
34   * compatible with the standard {@link ObjectInputStream}.  Please use
35   * {@link ObjectDecoder} or {@link ObjectDecoderInputStream} to ensure the
36   * interoperability with this encoder.
37   *
38   * @apiviz.landmark
39   * @apiviz.has org.jboss.netty.handler.codec.serialization.ObjectEncoderOutputStream - - - compatible with
40   */
41  @Sharable
42  public class ObjectEncoder extends OneToOneEncoder {
43      private static final byte[] LENGTH_PLACEHOLDER = new byte[4];
44  
45      private final int estimatedLength;
46  
47      /**
48       * Creates a new encoder with the estimated length of 512 bytes.
49       */
50      public ObjectEncoder() {
51          this(512);
52      }
53  
54      /**
55       * Creates a new encoder.
56       *
57       * @param estimatedLength
58       *        the estimated byte length of the serialized form of an object.
59       *        If the length of the serialized form exceeds this value, the
60       *        internal buffer will be expanded automatically at the cost of
61       *        memory bandwidth.  If this value is too big, it will also waste
62       *        memory bandwidth.  To avoid unnecessary memory copy or allocation
63       *        cost, please specify the properly estimated value.
64       */
65      public ObjectEncoder(int estimatedLength) {
66          if (estimatedLength < 0) {
67              throw new IllegalArgumentException(
68                      "estimatedLength: " + estimatedLength);
69          }
70          this.estimatedLength = estimatedLength;
71      }
72  
73      @Override
74      protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
75          ChannelBufferOutputStream bout =
76              new ChannelBufferOutputStream(dynamicBuffer(
77                      estimatedLength, ctx.getChannel().getConfig().getBufferFactory()));
78          bout.write(LENGTH_PLACEHOLDER);
79          ObjectOutputStream oout = new CompactObjectOutputStream(bout);
80          oout.writeObject(msg);
81          oout.flush();
82          oout.close();
83  
84          ChannelBuffer encoded = bout.buffer();
85          encoded.setInt(0, encoded.writerIndex() - 4);
86          return encoded;
87      }
88  }