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  }