/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.tcp;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UTFDataFormatException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIterator;

import org.apache.geode.DataSerializer;
import org.apache.geode.distributed.internal.DMStats;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.ByteBufferWriter;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.ObjToByteArraySerializer;
import org.apache.geode.internal.net.BufferPool;
import org.apache.geode.internal.serialization.StaticSerialization;
import org.apache.geode.internal.serialization.Version;

/**
 * <p>
 * MsgStreamer supports streaming a message to a tcp Connection in chunks. This allows us to send a
 * message without needing to perserialize it completely in memory thus saving buffer memory.
 *
 * @since GemFire 5.0.2
 *
 */

public class MsgStreamer extends OutputStream
    implements ObjToByteArraySerializer, BaseMsgStreamer, ByteBufferWriter {

  /**
   * List of connections to send this msg to.
   */
  private final List<?> cons;

  private final BufferPool bufferPool;

  /**
   * Any exceptions that happen during sends
   */
  private ConnectExceptions ce;
  /**
   * The byte buffer we used for preparing a chunk of the message. Currently this buffer is obtained
   * from the connection.
   */
  private final ByteBuffer buffer;
  private int flushedBytes = 0;
  // the message this streamer is to send
  private final DistributionMessage msg;
  /**
   * True if this message went out as a normal one (it fit it one chunk) False if this message
   * needed to be chunked.
   */
  private boolean normalMsg = false;
  /**
   * Set to true when we have started serializing a message. If this is true and doneWritingMsg is
   * false and we think we have finished writing the msg then we have a problem.
   */
  private boolean startedSerializingMsg = false;
  /**
   * Set to true after last byte of message has been written to this stream.
   */
  private boolean doneWritingMsg = false;
  private final DMStats stats;

  private short msgId;
  private long serStartTime;
  private final boolean directReply;

  /**
   * Called to free up resources used by this streamer after the streamer has produced its message.
   */
  protected void release() {
    MsgIdGenerator.release(this.msgId);
    this.buffer.clear();
    this.overflowBuf = null;
    bufferPool.releaseSenderBuffer(this.buffer);
  }

  /**
   * Returns an exception the describes which cons the message was not sent to. Call this after
   * {@link #writeMessage}.
   */
  @Override
  public ConnectExceptions getConnectExceptions() {
    return this.ce;
  }

  /**
   * Returns a list of the Connections that the message was sent to. Call this after
   * {@link #writeMessage}.
   */
  @Override
  public List<?> getSentConnections() {
    return this.cons;
  }

  /**
   * Create a msg streamer that will send the given msg to the given cons.
   *
   * Note: This is no longer supposed to be called directly rather the {@link #create} method should
   * now be used.
   */
  MsgStreamer(List<?> cons, DistributionMessage msg, boolean directReply, DMStats stats,
      int sendBufferSize, BufferPool bufferPool) {
    this.stats = stats;
    this.msg = msg;
    this.cons = cons;
    this.buffer = bufferPool.acquireDirectSenderBuffer(sendBufferSize);
    this.buffer.clear();
    this.buffer.position(Connection.MSG_HEADER_BYTES);
    this.msgId = MsgIdGenerator.NO_MSG_ID;
    this.directReply = directReply;
    this.bufferPool = bufferPool;
    startSerialization();
  }

  /**
   * Create message streamers splitting into versioned streamers, if required, for given list of
   * connections to remote nodes. This method can either return a single MsgStreamer object or a
   * List of MsgStreamer objects.
   */
  public static BaseMsgStreamer create(List<?> cons, final DistributionMessage msg,
      final boolean directReply, final DMStats stats, BufferPool bufferPool) {
    final Connection firstCon = (Connection) cons.get(0);
    // split into different versions if required
    Version version;
    final int numCons = cons.size();
    if (numCons > 1) {
      Connection con;
      Object2ObjectOpenHashMap versionToConnMap = null;
      int numVersioned = 0;
      for (Object c : cons) {
        con = (Connection) c;
        if ((version = con.getRemoteVersion()) != null) {
          if (versionToConnMap == null) {
            versionToConnMap = new Object2ObjectOpenHashMap();
          }
          @SuppressWarnings("unchecked")
          ArrayList<Object> vcons = (ArrayList<Object>) versionToConnMap.get(version);
          if (vcons == null) {
            vcons = new ArrayList<Object>(numCons);
            versionToConnMap.put(version, vcons);
          }
          vcons.add(con);
          numVersioned++;
        }
      }
      if (versionToConnMap == null) {
        return new MsgStreamer(cons, msg, directReply, stats, firstCon.getSendBufferSize(),
            bufferPool);
      } else {
        // if there is a versioned stream created, then split remaining
        // connections to unversioned stream
        final ArrayList<MsgStreamer> streamers =
            new ArrayList<MsgStreamer>(versionToConnMap.size() + 1);
        final int sendBufferSize = firstCon.getSendBufferSize();
        if (numCons > numVersioned) {
          // allocating list of numCons size so that as the result of
          // getSentConnections it may not need to be reallocted later
          final ArrayList<Object> unversionedCons = new ArrayList<Object>(numCons);
          for (Object c : cons) {
            con = (Connection) c;
            if ((version = con.getRemoteVersion()) == null) {
              unversionedCons.add(con);
            }
          }
          streamers.add(new MsgStreamer(unversionedCons, msg, directReply, stats, sendBufferSize,
              bufferPool));
        }
        for (ObjectIterator<Object2ObjectMap.Entry> itr =
            versionToConnMap.object2ObjectEntrySet().fastIterator(); itr.hasNext();) {
          Object2ObjectMap.Entry entry = itr.next();
          Object ver = entry.getKey();
          Object l = entry.getValue();
          streamers.add(new VersionedMsgStreamer((List<?>) l, msg, directReply, stats,
              bufferPool, sendBufferSize, (Version) ver));
        }
        return new MsgStreamerList(streamers);
      }
    } else if ((version = firstCon.getRemoteVersion()) == null) {
      return new MsgStreamer(cons, msg, directReply, stats, firstCon.getSendBufferSize(),
          bufferPool);
    } else {
      // create a single VersionedMsgStreamer
      return new VersionedMsgStreamer(cons, msg, directReply, stats, bufferPool,
          firstCon.getSendBufferSize(),
          version);
    }
  }

  /**
   * set connections to be "in use" and schedule alert tasks
   *
   */
  @Override
  public void reserveConnections(long startTime, long ackTimeout, long ackSDTimeout) {
    for (Iterator it = cons.iterator(); it.hasNext();) {
      Connection con = (Connection) it.next();
      con.setInUse(true, startTime, ackTimeout, ackSDTimeout, cons);
      if (ackTimeout > 0) {
        con.scheduleAckTimeouts();
      }
    }
  }

  private void startSerialization() {
    this.serStartTime = stats.startMsgSerialization();
  }

  /**
   * @throws IOException if serialization failure
   */
  @Override
  public int writeMessage() throws IOException {
    // if (logger.isTraceEnabled()) logger.trace(this.msg);

    try {
      this.startedSerializingMsg = true;
      InternalDataSerializer.writeDSFID(this.msg, this);
      this.doneWritingMsg = true;
      if (this.flushedBytes == 0) {
        // message fit in one chunk
        this.normalMsg = true;
      }
      realFlush(true);
      return this.flushedBytes;
    } finally {
      release();
    }
  }

  /** write the low-order 8 bits of the given int */
  @Override
  public void write(int b) {
    // if (logger.isTraceEnabled()) logger.trace(" byte={}", b);

    ensureCapacity(1);
    if (this.overflowBuf != null) {
      this.overflowBuf.write(b);
      return;
    }
    this.buffer.put((byte) (b & 0xff));
  }

  private void ensureCapacity(int amount) {
    if (this.overflowBuf != null) {
      return;
    }
    int remainingSpace = this.buffer.capacity() - this.buffer.position();
    if (amount > remainingSpace) {
      realFlush(false);
    }
  }

  @Override
  public void flush() {
    // this is a noop so that when ObjectOutputStream calls us
    // for each chunk from it we will not send data early to our connection.
  }

  private int overflowMode = 0;
  private HeapDataOutputStream overflowBuf = null;

  private boolean isOverflowMode() {
    return this.overflowMode > 0;
  }

  private void enableOverflowMode() {
    this.overflowMode++;
  }

  private void disableOverflowMode() {
    this.overflowMode--;
    if (!isOverflowMode()) {
      this.overflowBuf = null;
    }
  }

  public void realFlush(boolean lastFlushForMessage) {
    if (isOverflowMode()) {
      if (this.overflowBuf == null) {
        this.overflowBuf = new HeapDataOutputStream(
            this.buffer.capacity() - Connection.MSG_HEADER_BYTES, Version.CURRENT);
      }
      return;
    }
    this.buffer.flip();
    setMessageHeader();
    final int serializedBytes = this.buffer.limit();
    this.flushedBytes += serializedBytes;
    DistributionMessage conflationMsg = null;
    if (this.normalMsg) {
      // we can't conflate chunked messages; this fixes bug 36633
      conflationMsg = this.msg;
    }
    this.stats.endMsgSerialization(this.serStartTime);
    for (Iterator it = this.cons.iterator(); it.hasNext();) {
      Connection con = (Connection) it.next();
      try {
        con.sendPreserialized(this.buffer,
            lastFlushForMessage && this.msg.containsRegionContentChange(), conflationMsg);
      } catch (IOException ex) {
        it.remove();
        if (this.ce == null)
          this.ce = new ConnectExceptions();
        this.ce.addFailure(con.getRemoteAddress(), ex);
        con.closeForReconnect(
            String.format("closing due to %s", "IOException"));
      } catch (ConnectionException ex) {
        it.remove();
        if (this.ce == null)
          this.ce = new ConnectExceptions();
        this.ce.addFailure(con.getRemoteAddress(), ex);
        con.closeForReconnect(
            String.format("closing due to %s", "ConnectionException"));
      }
      this.buffer.rewind();
    }
    startSerialization();
    this.buffer.clear();
    this.buffer.position(Connection.MSG_HEADER_BYTES);
  }

  @Override
  public void close() throws IOException {
    try {
      if (this.startedSerializingMsg && !this.doneWritingMsg) {
        // if we wrote any bytes on the cnxs then we need to close them
        // since they have been corrupted by a partial serialization.
        if (this.flushedBytes > 0) {
          for (Iterator it = this.cons.iterator(); it.hasNext();) {
            Connection con = (Connection) it.next();
            con.closeForReconnect("Message serialization could not complete");
          }
        }
      }
    } finally {
      super.close();
    }
  }

  /** override OutputStream's write() */
  @Override
  public void write(byte[] source, int offset, int len) {
    // if (logger.isTraceEnabled()) {
    // logger.trace(" bytes={} offset={} len={}", source, offset, len);
    // }
    if (this.overflowBuf != null) {
      this.overflowBuf.write(source, offset, len);
      return;
    }
    while (len > 0) {
      int remainingSpace = this.buffer.capacity() - this.buffer.position();
      if (remainingSpace == 0) {
        realFlush(false);
        if (this.overflowBuf != null) {
          this.overflowBuf.write(source, offset, len);
          return;
        }
      } else {
        int chunkSize = remainingSpace;
        if (len < chunkSize) {
          chunkSize = len;
        }
        this.buffer.put(source, offset, chunkSize);
        offset += chunkSize;
        len -= chunkSize;
      }
    }
  }

  @Override
  public void write(ByteBuffer bb) {
    // if (logger.isTraceEnabled()) {
    // logger.trace(" bytes={} offset={} len={}", source, offset, len);
    // }
    if (this.overflowBuf != null) {
      this.overflowBuf.write(bb);
      return;
    }
    int len = bb.remaining();
    while (len > 0) {
      int remainingSpace = this.buffer.capacity() - this.buffer.position();
      if (remainingSpace == 0) {
        realFlush(false);
        if (this.overflowBuf != null) {
          this.overflowBuf.write(bb);
          return;
        }
      } else {
        int chunkSize = remainingSpace;
        if (len < chunkSize) {
          chunkSize = len;
        }
        int oldLimit = bb.limit();
        bb.limit(bb.position() + chunkSize);
        this.buffer.put(bb);
        bb.limit(oldLimit);
        len -= chunkSize;
      }
    }
  }

  /**
   * write the header after the message has been written to the stream
   */
  private void setMessageHeader() {
    Assert.assertTrue(this.overflowBuf == null);
    Assert.assertTrue(!isOverflowMode());
    // int processorType = this.msg.getProcessorType();
    int msgType;
    if (this.doneWritingMsg) {
      if (this.normalMsg) {
        msgType = Connection.NORMAL_MSG_TYPE;
      } else {
        msgType = Connection.END_CHUNKED_MSG_TYPE;
      }
      if (directReply) {
        msgType |= Connection.DIRECT_ACK_BIT;
      }
    } else {
      msgType = Connection.CHUNKED_MSG_TYPE;
    }
    if (!this.normalMsg) {
      if (this.msgId == MsgIdGenerator.NO_MSG_ID) {
        this.msgId = MsgIdGenerator.obtain();
      }
    }

    this.buffer.putInt(Connection.MSG_HEADER_SIZE_OFFSET,
        Connection.calcHdrSize(this.buffer.limit() - Connection.MSG_HEADER_BYTES));
    this.buffer.put(Connection.MSG_HEADER_TYPE_OFFSET, (byte) (msgType & 0xff));
    this.buffer.putShort(Connection.MSG_HEADER_ID_OFFSET, this.msgId);
    this.buffer.position(0);
  }

  // DataOutput methods
  /**
   * Writes a <code>boolean</code> value to this output stream. If the argument <code>v</code> is
   * <code>true</code>, the value <code>(byte)1</code> is written; if <code>v</code> is
   * <code>false</code>, the value <code>(byte)0</code> is written. The byte written by this method
   * may be read by the <code>readBoolean</code> method of interface <code>DataInput</code>, which
   * will then return a <code>boolean</code> equal to <code>v</code>.
   *
   * @param v the boolean to be written.
   */
  @Override
  public void writeBoolean(boolean v) {
    write(v ? 1 : 0);
  }

  /**
   * Writes to the output stream the eight low- order bits of the argument <code>v</code>. The 24
   * high-order bits of <code>v</code> are ignored. (This means that <code>writeByte</code> does
   * exactly the same thing as <code>write</code> for an integer argument.) The byte written by this
   * method may be read by the <code>readByte</code> method of interface <code>DataInput</code>,
   * which will then return a <code>byte</code> equal to <code>(byte)v</code>.
   *
   * @param v the byte value to be written.
   */
  @Override
  public void writeByte(int v) {
    write(v);
  }

  /**
   * Writes two bytes to the output stream to represent the value of the argument. The byte values
   * to be written, in the order shown, are:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xff &amp; (v &gt;&gt; 8))
   * (byte)(0xff &amp; v)
   * </code>
   * </pre>
   * <p>
   * The bytes written by this method may be read by the <code>readShort</code> method of interface
   * <code>DataInput</code> , which will then return a <code>short</code> equal to
   * <code>(short)v</code>.
   *
   * @param v the <code>short</code> value to be written.
   */
  @Override
  public void writeShort(int v) {
    // if (logger.isTraceEnabled()) logger.trace(" short={}", v);

    ensureCapacity(2);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeShort(v);
      return;
    }
    this.buffer.putShort((short) (v & 0xffff));
  }

  /**
   * Writes a <code>char</code> value, wich is comprised of two bytes, to the output stream. The
   * byte values to be written, in the order shown, are:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xff &amp; (v &gt;&gt; 8))
   * (byte)(0xff &amp; v)
   * </code>
   * </pre>
   * <p>
   * The bytes written by this method may be read by the <code>readChar</code> method of interface
   * <code>DataInput</code> , which will then return a <code>char</code> equal to
   * <code>(char)v</code>.
   *
   * @param v the <code>char</code> value to be written.
   */
  @Override
  public void writeChar(int v) {
    // if (logger.isTraceEnabled()) logger.trace(" char={}", v);

    ensureCapacity(2);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeChar(v);
      return;
    }
    this.buffer.putChar((char) v);
  }

  /**
   * Writes an <code>int</code> value, which is comprised of four bytes, to the output stream. The
   * byte values to be written, in the order shown, are:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xff &amp; (v &gt;&gt; 24))
   * (byte)(0xff &amp; (v &gt;&gt; 16))
   * (byte)(0xff &amp; (v &gt;&gt; &#32; &#32;8))
   * (byte)(0xff &amp; v)
   * </code>
   * </pre>
   * <p>
   * The bytes written by this method may be read by the <code>readInt</code> method of interface
   * <code>DataInput</code> , which will then return an <code>int</code> equal to <code>v</code>.
   *
   * @param v the <code>int</code> value to be written.
   */
  @Override
  public void writeInt(int v) {
    // if (logger.isTraceEnabled()) logger.trace(" int={}", v);

    ensureCapacity(4);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeInt(v);
      return;
    }
    this.buffer.putInt(v);
  }

  /**
   * Writes a <code>long</code> value, which is comprised of eight bytes, to the output stream. The
   * byte values to be written, in the order shown, are:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xff &amp; (v &gt;&gt; 56))
   * (byte)(0xff &amp; (v &gt;&gt; 48))
   * (byte)(0xff &amp; (v &gt;&gt; 40))
   * (byte)(0xff &amp; (v &gt;&gt; 32))
   * (byte)(0xff &amp; (v &gt;&gt; 24))
   * (byte)(0xff &amp; (v &gt;&gt; 16))
   * (byte)(0xff &amp; (v &gt;&gt;  8))
   * (byte)(0xff &amp; v)
   * </code>
   * </pre>
   * <p>
   * The bytes written by this method may be read by the <code>readLong</code> method of interface
   * <code>DataInput</code> , which will then return a <code>long</code> equal to <code>v</code>.
   *
   * @param v the <code>long</code> value to be written.
   */
  @Override
  public void writeLong(long v) {
    // if (logger.isTraceEnabled()) logger.trace(" long={}", v);

    ensureCapacity(8);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeLong(v);
      return;
    }
    this.buffer.putLong(v);
  }

  /**
   * Writes a <code>float</code> value, which is comprised of four bytes, to the output stream. It
   * does this as if it first converts this <code>float</code> value to an <code>int</code> in
   * exactly the manner of the <code>Float.floatToIntBits</code> method and then writes the
   * <code>int</code> value in exactly the manner of the <code>writeInt</code> method. The bytes
   * written by this method may be read by the <code>readFloat</code> method of interface
   * <code>DataInput</code>, which will then return a <code>float</code> equal to <code>v</code>.
   *
   * @param v the <code>float</code> value to be written.
   */
  @Override
  public void writeFloat(float v) {
    // if (logger.isTraceEnabled()) logger.trace(" float={}", v);

    ensureCapacity(4);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeFloat(v);
      return;
    }
    this.buffer.putFloat(v);
  }

  /**
   * Writes a <code>double</code> value, which is comprised of eight bytes, to the output stream. It
   * does this as if it first converts this <code>double</code> value to a <code>long</code> in
   * exactly the manner of the <code>Double.doubleToLongBits</code> method and then writes the
   * <code>long</code> value in exactly the manner of the <code>writeLong</code> method. The bytes
   * written by this method may be read by the <code>readDouble</code> method of interface
   * <code>DataInput</code>, which will then return a <code>double</code> equal to <code>v</code>.
   *
   * @param v the <code>double</code> value to be written.
   */
  @Override
  public void writeDouble(double v) {
    // if (logger.isTraceEnabled()) logger.trace(" double={}", v);

    ensureCapacity(8);
    if (this.overflowBuf != null) {
      this.overflowBuf.writeDouble(v);
      return;
    }
    this.buffer.putDouble(v);
  }

  /**
   * Writes a string to the output stream. For every character in the string <code>s</code>, taken
   * in order, one byte is written to the output stream. If <code>s</code> is <code>null</code>, a
   * <code>NullPointerException</code> is thrown.
   * <p>
   * If <code>s.length</code> is zero, then no bytes are written. Otherwise, the character
   * <code>s[0]</code> is written first, then <code>s[1]</code>, and so on; the last character
   * written is <code>s[s.length-1]</code>. For each character, one byte is written, the low-order
   * byte, in exactly the manner of the <code>writeByte</code> method . The high-order eight bits of
   * each character in the string are ignored.
   *
   * @param str the string of bytes to be written.
   */
  @Override
  public void writeBytes(String str) {
    // if (logger.isTraceEnabled()) logger.trace(" bytes={}", str);

    if (this.overflowBuf != null) {
      this.overflowBuf.writeBytes(str);
      return;
    }
    int strlen = str.length();
    if (strlen > 0) {
      for (int i = 0; i < strlen; i++) {
        writeByte((byte) str.charAt(i));
      }
    }
  }

  /**
   * Writes every character in the string <code>s</code>, to the output stream, in order, two bytes
   * per character. If <code>s</code> is <code>null</code>, a <code>NullPointerException</code> is
   * thrown. If <code>s.length</code> is zero, then no characters are written. Otherwise, the
   * character <code>s[0]</code> is written first, then <code>s[1]</code>, and so on; the last
   * character written is <code>s[s.length-1]</code>. For each character, two bytes are actually
   * written, high-order byte first, in exactly the manner of the <code>writeChar</code> method.
   *
   * @param s the string value to be written.
   */
  @Override
  public void writeChars(String s) {
    // if (logger.isTraceEnabled()) logger.trace(" chars={}", s);

    if (this.overflowBuf != null) {
      this.overflowBuf.writeChars(s);
      return;
    }
    int len = s.length();
    int offset = 0;
    while (len > 0) {
      int remainingCharSpace = (this.buffer.capacity() - this.buffer.position()) / 2;
      if (remainingCharSpace == 0) {
        realFlush(false);
        if (this.overflowBuf != null) {
          this.overflowBuf.writeChars(s.substring(offset));
          return;
        }
      } else {
        int chunkSize = remainingCharSpace;
        if (len < chunkSize) {
          chunkSize = len;
        }
        for (int i = 0; i < chunkSize; i++) {
          this.buffer.putChar(s.charAt(offset + i));
        }
        offset += chunkSize;
        len -= chunkSize;
      }
    }
  }

  /**
   * Use -Dgemfire.ASCII_STRINGS=true if all String instances contain ASCII characters. Setting this
   * to true gives a performance improvement.
   */
  private static final boolean ASCII_STRINGS =
      Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "ASCII_STRINGS");

  /**
   * Writes two bytes of length information to the output stream, followed by the Java modified UTF
   * representation of every character in the string <code>s</code>. If <code>s</code> is
   * <code>null</code>, a <code>NullPointerException</code> is thrown. Each character in the string
   * <code>s</code> is converted to a group of one, two, or three bytes, depending on the value of
   * the character.
   * <p>
   * If a character <code>c</code> is in the range <code>&#92;u0001</code> through
   * <code>&#92;u007f</code>, it is represented by one byte:
   * <p>
   *
   * <pre>
   * (byte) c
   * </pre>
   * <p>
   * If a character <code>c</code> is <code>&#92;u0000</code> or is in the range
   * <code>&#92;u0080</code> through <code>&#92;u07ff</code>, then it is represented by two bytes,
   * to be written in the order shown:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xc0 | (0x1f &amp; (c &gt;&gt; 6)))
   * (byte)(0x80 | (0x3f &amp; c))
   *  </code>
   * </pre>
   * <p>
   * If a character <code>c</code> is in the range <code>&#92;u0800</code> through
   * <code>uffff</code>, then it is represented by three bytes, to be written in the order shown:
   * <p>
   *
   * <pre>
   * <code>
   * (byte)(0xe0 | (0x0f &amp; (c &gt;&gt; 12)))
   * (byte)(0x80 | (0x3f &amp; (c &gt;&gt;  6)))
   * (byte)(0x80 | (0x3f &amp; c))
   *  </code>
   * </pre>
   * <p>
   * First, the total number of bytes needed to represent all the characters of <code>s</code> is
   * calculated. If this number is larger than <code>65535</code>, then a
   * <code>UTFDataFormatException</code> is thrown. Otherwise, this length is written to the output
   * stream in exactly the manner of the <code>writeShort</code> method; after this, the one-, two-,
   * or three-byte representation of each character in the string <code>s</code> is written.
   * <p>
   * The bytes written by this method may be read by the <code>readUTF</code> method of interface
   * <code>DataInput</code> , which will then return a <code>String</code> equal to <code>s</code>.
   *
   * @param str the string value to be written.
   * @exception IOException if an I/O error occurs.
   */
  @Override
  public void writeUTF(String str) throws IOException {
    // if (logger.isTraceEnabled()) logger.trace(" utf={}", str);

    if (this.overflowBuf != null) {
      this.overflowBuf.writeUTF(str);
      return;
    }
    if (ASCII_STRINGS) {
      writeAsciiUTF(str);
    } else {
      writeFullUTF(str);
    }
  }

  private void writeAsciiUTF(String str) throws IOException {
    int len = str.length();
    if (len > 65535) {
      throw new UTFDataFormatException();
    }
    writeShort(len);
    int offset = 0;
    while (len > 0) {
      int remainingSpace = this.buffer.capacity() - this.buffer.position();
      if (remainingSpace == 0) {
        realFlush(false);
        if (this.overflowBuf != null) {
          this.overflowBuf.write(str.substring(offset).getBytes());
          return;
        }
      } else {
        int chunkSize = remainingSpace;
        if (len < chunkSize) {
          chunkSize = len;
        }
        for (int i = 0; i < chunkSize; i++) {
          this.buffer.put((byte) str.charAt(offset + i));
        }
        offset += chunkSize;
        len -= chunkSize;
      }
    }
  }

  private void writeFullUTF(String str) throws IOException {
    int strlen = str.length();
    if (strlen > 65535) {
      throw new UTFDataFormatException();
    }
    {
      int remainingSpace = this.buffer.capacity() - this.buffer.position();
      if (remainingSpace >= ((strlen * 3) + 2)) {
        // we have plenty of room to do this with one pass directly into the buffer
        writeQuickFullUTF(str, strlen);
        return;
      }
    }
    int utfSize = 0;
    for (int i = 0; i < strlen; i++) {
      int c = str.charAt(i);
      if ((c >= 0x0001) && (c <= 0x007F)) {
        utfSize += 1;
      } else if (c > 0x07FF) {
        utfSize += 3;
      } else {
        utfSize += 2;
      }
    }
    if (utfSize > 65535) {
      throw new UTFDataFormatException();
    }
    writeShort(utfSize);
    for (int i = 0; i < strlen; i++) {
      int c = str.charAt(i);
      if ((c >= 0x0001) && (c <= 0x007F)) {
        writeByte((byte) c);
      } else if (c > 0x07FF) {
        writeByte((byte) (0xE0 | ((c >> 12) & 0x0F)));
        writeByte((byte) (0x80 | ((c >> 6) & 0x3F)));
        writeByte((byte) (0x80 | ((c >> 0) & 0x3F)));
      } else {
        writeByte((byte) (0xC0 | ((c >> 6) & 0x1F)));
        writeByte((byte) (0x80 | ((c >> 0) & 0x3F)));
      }
    }
  }

  /**
   * Used when we know the max size will fit in the current buffer.
   */
  private void writeQuickFullUTF(String str, int strlen) throws IOException {
    int utfSizeIdx = this.buffer.position();
    // skip bytes reserved for length
    this.buffer.position(utfSizeIdx + 2);
    for (int i = 0; i < strlen; i++) {
      int c = str.charAt(i);
      if ((c >= 0x0001) && (c <= 0x007F)) {
        this.buffer.put((byte) c);
      } else if (c > 0x07FF) {
        this.buffer.put((byte) (0xE0 | ((c >> 12) & 0x0F)));
        this.buffer.put((byte) (0x80 | ((c >> 6) & 0x3F)));
        this.buffer.put((byte) (0x80 | ((c >> 0) & 0x3F)));
      } else {
        this.buffer.put((byte) (0xC0 | ((c >> 6) & 0x1F)));
        this.buffer.put((byte) (0x80 | ((c >> 0) & 0x3F)));
      }
    }
    int utflen = this.buffer.position() - (utfSizeIdx + 2);
    if (utflen > 65535) {
      // act as if we wrote nothing to this buffer
      this.buffer.position(utfSizeIdx);
      throw new UTFDataFormatException();
    }
    this.buffer.putShort(utfSizeIdx, (short) utflen);
  }

  /**
   * Attempt to fit v into the current buffer as a serialized byte array. This is done by reserving
   * 5 bytes for the length and then starting the serialization. If all the bytes fit then the
   * length is fixed up and we are done. If it doesn't fit then we need to serialize the remainder
   * to a temporary HeapDataOutputStream and then fix the length flush the first chunk and then send
   * the contents of the HeapDataOutputStream to this streamer. All of this is done to prevent an
   * extra copy when the serialized form will all fit into our current buffer.
   */
  @Override
  public void writeAsSerializedByteArray(Object v) throws IOException {
    if (v instanceof HeapDataOutputStream) {
      HeapDataOutputStream other = (HeapDataOutputStream) v;
      InternalDataSerializer.writeArrayLength(other.size(), this);
      other.sendTo((ByteBufferWriter) this);
      other.rewind();
      return;
    }
    if (this.overflowBuf != null) {
      this.overflowBuf.writeAsSerializedByteArray(v);
      return;
    }
    if (isOverflowMode()) {
      // we must have recursed which is now allowed to fix bug 38194
      int remainingSpace = this.buffer.capacity() - this.buffer.position();
      if (remainingSpace < 5) {
        // we don't even have room to write the length field so just create
        // the overflowBuf
        this.overflowBuf = new HeapDataOutputStream(
            this.buffer.capacity() - Connection.MSG_HEADER_BYTES, Version.CURRENT);
        this.overflowBuf.writeAsSerializedByteArray(v);
        return;
      }
    } else {
      ensureCapacity(5 + 1024); /*
                                 * need 5 bytes for length plus enough room for an 'average' small
                                 * object. I pulled 1024 as the average out of thin air.
                                 */
    }
    int lengthPos = this.buffer.position();
    this.buffer.position(lengthPos + 5);
    enableOverflowMode();
    boolean finished = false;
    try {
      try {
        DataSerializer.writeObject(v, this);
      } catch (IOException e) {
        RuntimeException e2 = new IllegalArgumentException(
            "An Exception was thrown while serializing.");
        e2.initCause(e);
        throw e2;
      }
      int baLength = this.buffer.position() - (lengthPos + 5);
      HeapDataOutputStream overBuf = this.overflowBuf;
      if (overBuf != null) {
        baLength += overBuf.size();
      }
      this.buffer.put(lengthPos, StaticSerialization.INT_ARRAY_LEN);
      this.buffer.putInt(lengthPos + 1, baLength);
      disableOverflowMode();
      finished = true;
      if (overBuf != null && !isOverflowMode()) {
        overBuf.sendTo((ByteBufferWriter) this);
      }
    } finally {
      if (!finished) {
        // reset buffer and act as if we did nothing
        this.buffer.position(lengthPos);
        disableOverflowMode();
      }
    }
  }


}
