mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
28.47.2010 f2160f4bd1c8ac67e5a86a6710d431e8932877f9
sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java
File was renamed from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.java
@@ -22,16 +22,18 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2010 Sun Microsystems, Inc.
 */
package com.sun.opends.sdk.ldap;
import static com.sun.opends.sdk.messages.Messages.*;
import static org.opends.sdk.asn1.ASN1Constants.*;
import static com.sun.opends.sdk.messages.Messages.ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED;
import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_FALSE;
import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_TRUE;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import org.opends.sdk.ByteSequence;
@@ -40,8 +42,10 @@
import org.opends.sdk.asn1.ASN1Writer;
import org.opends.sdk.asn1.AbstractASN1Writer;
import com.sun.grizzly.streams.StreamWriter;
import com.sun.grizzly.utils.PoolableObject;
import com.sun.grizzly.Buffer;
import com.sun.grizzly.Cacheable;
import com.sun.grizzly.ThreadCache;
import com.sun.grizzly.memory.ByteBufferWrapper;
import com.sun.opends.sdk.util.StaticUtils;
@@ -49,8 +53,8 @@
/**
 * Grizzly ASN1 writer implementation.
 */
public final class ASN1StreamWriter extends AbstractASN1Writer implements
    ASN1Writer, PoolableObject
final class ASN1BufferWriter extends AbstractASN1Writer implements ASN1Writer,
    Cacheable
{
  private class ChildSequenceBuffer implements SequenceBuffer
  {
@@ -59,15 +63,14 @@
    private ChildSequenceBuffer child;
    private final ByteStringBuilder buffer = new ByteStringBuilder(
        SUB_SEQUENCE_BUFFER_INIT_SIZE);
        BUFFER_INIT_SIZE);
    public SequenceBuffer endSequence() throws IOException
    {
      writeLength(parent, buffer.length());
      parent.writeByteArray(buffer.getBackingArray(), 0, buffer
          .length());
      parent.writeByteArray(buffer.getBackingArray(), 0, buffer.length());
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
@@ -80,7 +83,7 @@
    public SequenceBuffer startSequence(byte type) throws IOException
    public SequenceBuffer startSequence(final byte type) throws IOException
    {
      if (child == null)
      {
@@ -96,15 +99,15 @@
    public void writeByte(byte b) throws IOException
    public void writeByte(final byte b) throws IOException
    {
      buffer.append(b);
    }
    public void writeByteArray(byte[] bs, int offset, int length)
        throws IOException
    public void writeByteArray(final byte[] bs, final int offset,
        final int length) throws IOException
    {
      buffer.append(bs, offset, length);
    }
@@ -112,6 +115,59 @@
  private static final class RecyclableBuffer extends ByteBufferWrapper
  {
    private volatile boolean usable = true;
    private RecyclableBuffer()
    {
      visible = ByteBuffer.allocate(BUFFER_INIT_SIZE);
      allowBufferDispose = true;
    }
    @Override
    public void dispose()
    {
      usable = true;
    }
    /**
     * Ensures that the specified number of additional bytes will fit in the
     * buffer and resizes it if necessary.
     *
     * @param size
     *          The number of additional bytes.
     */
    public void ensureAdditionalCapacity(final int size)
    {
      final int newCount = visible.position() + size;
      if (newCount > visible.capacity())
      {
        final ByteBuffer newByteBuffer = ByteBuffer.allocate(Math.max(visible
            .capacity() << 1, newCount));
        visible.flip();
        visible = newByteBuffer.put(visible);
      }
    }
    @Override
    public ByteBufferWrapper flip()
    {
      usable = false;
      return super.flip();
    }
  }
  private class RootSequenceBuffer implements SequenceBuffer
  {
    private ChildSequenceBuffer child;
@@ -120,13 +176,14 @@
    public SequenceBuffer endSequence() throws IOException
    {
      LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED.get();
      final LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED
          .get();
      throw new IllegalStateException(message.toString());
    }
    public SequenceBuffer startSequence(byte type) throws IOException
    public SequenceBuffer startSequence(final byte type) throws IOException
    {
      if (child == null)
      {
@@ -134,7 +191,8 @@
        child.parent = this;
      }
      streamWriter.writeByte(type);
      outBuffer.ensureAdditionalCapacity(1);
      outBuffer.put(type);
      child.buffer.clear();
      return child;
@@ -142,17 +200,19 @@
    public void writeByte(byte b) throws IOException
    public void writeByte(final byte b) throws IOException
    {
      streamWriter.writeByte(b);
      outBuffer.ensureAdditionalCapacity(1);
      outBuffer.put(b);
    }
    public void writeByteArray(byte[] bs, int offset, int length)
        throws IOException
    public void writeByteArray(final byte[] bs, final int offset,
        final int length) throws IOException
    {
      streamWriter.writeByteArray(bs, offset, length);
      outBuffer.ensureAdditionalCapacity(length);
      outBuffer.put(bs, offset, length);
    }
  }
@@ -178,11 +238,33 @@
  private static final int SUB_SEQUENCE_BUFFER_INIT_SIZE = 1024;
  private static final int BUFFER_INIT_SIZE = 1024;
  private final static ThreadCache.CachedTypeIndex<ASN1BufferWriter> WRITER_INDEX = ThreadCache
      .obtainIndex(ASN1BufferWriter.class, 1);
  private StreamWriter streamWriter;
  static ASN1BufferWriter getWriter()
  {
    ASN1BufferWriter asn1Writer = ThreadCache.takeFromCache(WRITER_INDEX);
    if (asn1Writer == null)
    {
      asn1Writer = new ASN1BufferWriter();
    }
    if (!asn1Writer.outBuffer.usable)
    {
      // If the output buffer is unusable, create a new one.
      asn1Writer.outBuffer = new RecyclableBuffer();
    }
    asn1Writer.outBuffer.clear();
    return asn1Writer;
  }
  private SequenceBuffer sequenceBuffer;
  private RecyclableBuffer outBuffer;
  private final RootSequenceBuffer rootBuffer;
@@ -191,23 +273,24 @@
  /**
   * Creates a new ASN.1 writer that writes to a StreamWriter.
   */
  public ASN1StreamWriter()
  private ASN1BufferWriter()
  {
    this.sequenceBuffer = this.rootBuffer = new RootSequenceBuffer();
    this.outBuffer = new RecyclableBuffer();
  }
  /**
   * Closes this ASN.1 writer and the underlying outputstream. Any
   * unfinished sequences will be ended.
   * Closes this ASN.1 writer and the underlying outputstream. Any unfinished
   * sequences will be ended.
   *
   * @throws IOException
   *           if an error occurs while closing the stream.
   */
  public void close() throws IOException
  {
    streamWriter.close();
    outBuffer = null;
  }
@@ -220,29 +303,16 @@
   */
  public void flush() throws IOException
  {
    streamWriter.flush();
    // Do nothing
  }
  public void prepare()
  public void recycle()
  {
    // nothing to do
  }
  public void release()
  {
    streamWriter = null;
    sequenceBuffer = rootBuffer;
  }
  public void setStreamWriter(StreamWriter streamWriter)
  {
    this.streamWriter = streamWriter;
    outBuffer.clear();
    ThreadCache.putToCache(WRITER_INDEX, this);
  }
@@ -250,7 +320,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeBoolean(byte type, boolean booleanValue)
  public ASN1Writer writeBoolean(final byte type, final boolean booleanValue)
      throws IOException
  {
    sequenceBuffer.writeByte(type);
@@ -261,8 +331,8 @@
    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
    {
      StaticUtils.DEBUG_LOG.finest(String.format(
          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type,
          1, String.valueOf(booleanValue)));
          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type, 1,
          String.valueOf(booleanValue)));
    }
    return this;
  }
@@ -295,7 +365,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeEnumerated(byte type, int intValue)
  public ASN1Writer writeEnumerated(final byte type, final int intValue)
      throws IOException
  {
    return writeInteger(type, intValue);
@@ -306,7 +376,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeInteger(byte type, int intValue)
  public ASN1Writer writeInteger(final byte type, final int intValue)
      throws IOException
  {
    sequenceBuffer.writeByte(type);
@@ -318,8 +388,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 1, intValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
            intValue));
      }
    }
    else if (((intValue < 0) && ((intValue & 0xFFFF8000) == 0xFFFF8000))
@@ -331,8 +401,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 2, intValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
            intValue));
      }
    }
    else if (((intValue < 0) && ((intValue & 0xFF800000) == 0xFF800000))
@@ -345,8 +415,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 3, intValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
            intValue));
      }
    }
    else
@@ -359,8 +429,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 4, intValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
            intValue));
      }
    }
    return this;
@@ -371,7 +441,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeInteger(byte type, long longValue)
  public ASN1Writer writeInteger(final byte type, final long longValue)
      throws IOException
  {
    sequenceBuffer.writeByte(type);
@@ -383,8 +453,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 1, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L))
@@ -396,8 +466,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 2, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L))
@@ -410,8 +480,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 3, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L))
@@ -425,8 +495,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 4, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L))
@@ -441,8 +511,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 5, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 5,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L))
@@ -458,8 +528,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 6, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 6,
            longValue));
      }
    }
    else if (((longValue < 0) && ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L))
@@ -476,8 +546,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 7, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 7,
            longValue));
      }
    }
    else
@@ -494,8 +564,8 @@
      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
      {
        StaticUtils.DEBUG_LOG.finest(String.format(
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
            type, 8, longValue));
            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 8,
            longValue));
      }
    }
    return this;
@@ -506,7 +576,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeNull(byte type) throws IOException
  public ASN1Writer writeNull(final byte type) throws IOException
  {
    sequenceBuffer.writeByte(type);
    writeLength(sequenceBuffer, 0);
@@ -524,8 +594,8 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeOctetString(byte type, byte[] value,
      int offset, int length) throws IOException
  public ASN1Writer writeOctetString(final byte type, final byte[] value,
      final int offset, final int length) throws IOException
  {
    sequenceBuffer.writeByte(type);
    writeLength(sequenceBuffer, length);
@@ -533,9 +603,8 @@
    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
    {
      StaticUtils.DEBUG_LOG.finest(String
          .format("WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)",
              type, length));
      StaticUtils.DEBUG_LOG.finest(String.format(
          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, length));
    }
    return this;
  }
@@ -545,7 +614,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeOctetString(byte type, ByteSequence value)
  public ASN1Writer writeOctetString(final byte type, final ByteSequence value)
      throws IOException
  {
    sequenceBuffer.writeByte(type);
@@ -558,8 +627,8 @@
    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
    {
      StaticUtils.DEBUG_LOG.finest(String.format(
          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
      StaticUtils.DEBUG_LOG.finest(String
          .format("WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
              .length()));
    }
    return this;
@@ -570,7 +639,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeOctetString(byte type, String value)
  public ASN1Writer writeOctetString(final byte type, final String value)
      throws IOException
  {
    sequenceBuffer.writeByte(type);
@@ -581,15 +650,15 @@
      return this;
    }
    byte[] bytes = StaticUtils.getBytes(value);
    final byte[] bytes = StaticUtils.getBytes(value);
    writeLength(sequenceBuffer, bytes.length);
    sequenceBuffer.writeByteArray(bytes, 0, bytes.length);
    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
    {
      StaticUtils.DEBUG_LOG.finest(String.format(
          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, "
              + "value=%s)", type, bytes.length, value));
          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, " + "value=%s)", type,
          bytes.length, value));
    }
    return this;
  }
@@ -599,7 +668,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeStartSequence(byte type) throws IOException
  public ASN1Writer writeStartSequence(final byte type) throws IOException
  {
    // Get a child sequence buffer
    sequenceBuffer = sequenceBuffer.startSequence(type);
@@ -617,7 +686,7 @@
  /**
   * {@inheritDoc}
   */
  public ASN1Writer writeStartSet(byte type) throws IOException
  public ASN1Writer writeStartSet(final byte type) throws IOException
  {
    // From an implementation point of view, a set is equivalent to a
    // sequence.
@@ -626,9 +695,15 @@
  Buffer getBuffer()
  {
    return outBuffer.flip();
  }
  /**
   * Writes the provided value for use as the length of an ASN.1
   * element.
   * Writes the provided value for use as the length of an ASN.1 element.
   *
   * @param buffer
   *          The sequence buffer to write to.
@@ -637,7 +712,7 @@
   * @throws IOException
   *           if an error occurs while writing.
   */
  private void writeLength(SequenceBuffer buffer, int length)
  private void writeLength(final SequenceBuffer buffer, final int length)
      throws IOException
  {
    if (length < 128)