From 263d085885df024dca9250cc03c807912b0a7662 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 24 Apr 2012 22:33:21 +0000
Subject: [PATCH] Reformat to comply with new Checkstyle rules.

---
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ASN1BufferReader.java | 1238 +++++++++++++++++++++++++---------------------------------
 1 files changed, 533 insertions(+), 705 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ASN1BufferReader.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ASN1BufferReader.java
index 22a83b6..8a47862 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ASN1BufferReader.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ASN1BufferReader.java
@@ -6,17 +6,16 @@
  * (the "License").  You may not use this file except in compliance
  * with the License.
  *
- * You can obtain a copy of the license at
- * trunk/opendj3/legal-notices/CDDLv1_0.txt
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
  * or http://forgerock.org/license/CDDLv1.0.html.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
  * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
@@ -28,9 +27,10 @@
 
 package com.forgerock.opendj.ldap;
 
-
-
-import static com.forgerock.opendj.ldap.LDAPConstants.*;
+import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
+import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
+import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_TYPE;
+import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_VALUE_BYTES;
 import static org.forgerock.opendj.ldap.CoreMessages.*;
 
 import java.io.IOException;
@@ -49,770 +49,598 @@
 
 import com.forgerock.opendj.util.StaticUtils;
 
-
-
 /**
  * Grizzly ASN1 reader implementation.
  */
-final class ASN1BufferReader extends AbstractASN1Reader implements ASN1Reader
-{
-  private final class ChildSequenceLimiter implements SequenceLimiter
-  {
-    private SequenceLimiter parent;
+final class ASN1BufferReader extends AbstractASN1Reader implements ASN1Reader {
+    private final class ChildSequenceLimiter implements SequenceLimiter {
+        private SequenceLimiter parent;
 
-    private ChildSequenceLimiter child;
+        private ChildSequenceLimiter child;
 
-    private int readLimit;
+        private int readLimit;
 
-    private int bytesRead;
+        private int bytesRead;
 
+        public void checkLimit(final int readSize) throws IOException {
+            if ((readLimit > 0) && (bytesRead + readSize > readLimit)) {
+                final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+                throw DecodeException.fatalError(message);
+            }
 
+            parent.checkLimit(readSize);
 
-    public void checkLimit(final int readSize) throws IOException
-    {
-      if ((readLimit > 0) && (bytesRead + readSize > readLimit))
-      {
-        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
-        throw DecodeException.fatalError(message);
-      }
-
-      parent.checkLimit(readSize);
-
-      bytesRead += readSize;
-    }
-
-
-
-    public SequenceLimiter endSequence() throws IOException
-    {
-      parent.checkLimit(remaining());
-
-      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE) && remaining() > 0)
-      {
-        StaticUtils.DEBUG_LOG
-            .fine(String.format(
-                "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE",
-                remaining()));
-      }
-
-      for (int i = 0; i < remaining(); i++)
-      {
-        buffer.get();
-      }
-
-      return parent;
-    }
-
-
-
-    public int remaining()
-    {
-      return readLimit - bytesRead;
-    }
-
-
-
-    public ChildSequenceLimiter startSequence(final int readLimit)
-    {
-      if (child == null)
-      {
-        child = new ChildSequenceLimiter();
-        child.parent = this;
-      }
-
-      child.readLimit = readLimit;
-      child.bytesRead = 0;
-
-      return child;
-    }
-  }
-
-
-
-  private final class RootSequenceLimiter implements SequenceLimiter
-  {
-    private ChildSequenceLimiter child;
-
-
-
-    public void checkLimit(final int readSize) throws IOException
-    {
-      if (buffer.remaining() < readSize)
-      {
-        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
-        throw DecodeException.fatalError(message);
-      }
-    }
-
-
-
-    public ChildSequenceLimiter endSequence() throws DecodeException
-    {
-      final LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED
-          .get();
-      throw new IllegalStateException(message.toString());
-    }
-
-
-
-    public int remaining()
-    {
-      return buffer.remaining();
-    }
-
-
-
-    public ChildSequenceLimiter startSequence(final int readLimit)
-    {
-      if (child == null)
-      {
-        child = new ChildSequenceLimiter();
-        child.parent = this;
-      }
-
-      child.readLimit = readLimit;
-      child.bytesRead = 0;
-
-      return child;
-    }
-  }
-
-
-
-  private interface SequenceLimiter
-  {
-    public void checkLimit(int readSize) throws IOException;
-
-
-
-    public SequenceLimiter endSequence() throws IOException;
-
-
-
-    public int remaining();
-
-
-
-    public SequenceLimiter startSequence(int readLimit);
-  }
-
-
-
-  private static final int MAX_STRING_BUFFER_SIZE = 1024;
-
-  private int state = ELEMENT_READ_STATE_NEED_TYPE;
-
-  private byte peekType = 0;
-
-  private int peekLength = -1;
-
-  private int lengthBytesNeeded = 0;
-
-  private final int maxElementSize;
-
-  private final CompositeBuffer buffer;
-
-  private SequenceLimiter readLimiter;
-
-  private final byte[] stringBuffer;
-
-
-
-  /**
-   * Creates a new ASN1 reader whose source is the provided input stream and
-   * having a user defined maximum BER element size.
-   *
-   * @param maxElementSize
-   *          The maximum BER element size, or <code>0</code> to indicate that
-   *          there is no limit.
-   * @param memoryManager
-   *          The memory manager to use for buffering.
-   */
-  ASN1BufferReader(final int maxElementSize,
-      final MemoryManager<?> memoryManager)
-  {
-    this.readLimiter = new RootSequenceLimiter();
-    this.stringBuffer = new byte[MAX_STRING_BUFFER_SIZE];
-    this.maxElementSize = maxElementSize;
-    this.buffer = BuffersBuffer.create(memoryManager);
-  }
-
-
-
-  /**
-   * Closes this ASN.1 reader and the underlying stream.
-   *
-   * @throws IOException
-   *           if an I/O error occurs
-   */
-  public void close() throws IOException
-  {
-    buffer.dispose();
-  }
-
-
-
-  /**
-   * Determines if a complete ASN.1 element is ready to be read from the stream
-   * reader.
-   *
-   * @return <code>true</code> if another complete element is available or
-   *         <code>false</code> otherwise.
-   * @throws IOException
-   *           If an error occurs while trying to decode an ASN1 element.
-   */
-  public boolean elementAvailable() throws IOException
-  {
-    return !((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(true))
-        && !((state == ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE)
-            && !needFirstLengthByteState(true))
-        && !((state == ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES)
-            && !needAdditionalLengthBytesState(true))
-        && peekLength <= readLimiter.remaining();
-
-  }
-
-
-
-  /**
-   * Determines if the input stream contains at least one ASN.1 element to be
-   * read.
-   *
-   * @return <code>true</code> if another element is available or
-   *         <code>false</code> otherwise.
-   * @throws IOException
-   *           If an error occurs while trying to decode an ASN1 element.
-   */
-  public boolean hasNextElement() throws IOException
-  {
-    return (state != ELEMENT_READ_STATE_NEED_TYPE) || needTypeState(true);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public int peekLength() throws IOException
-  {
-    peekType();
-
-    switch (state)
-    {
-    case ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE:
-      needFirstLengthByteState(false);
-      break;
-
-    case ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES:
-      needAdditionalLengthBytesState(false);
-    }
-
-    return peekLength;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public byte peekType() throws IOException
-  {
-    if (state == ELEMENT_READ_STATE_NEED_TYPE)
-    {
-      needTypeState(false);
-    }
-
-    return peekType;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean readBoolean() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if (peekLength != 1)
-    {
-      final LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH
-          .get(peekLength);
-      throw DecodeException.fatalError(message);
-    }
-
-    readLimiter.checkLimit(peekLength);
-    final byte readByte = buffer.get();
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", peekType,
-          peekLength, String.valueOf(readByte != 0x00)));
-    }
-
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-    return readByte != 0x00;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void readEndSequence() throws IOException
-  {
-    readLimiter = readLimiter.endSequence();
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format("READ ASN.1 END SEQUENCE"));
-    }
-
-    // Reset the state
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void readEndSet() throws IOException
-  {
-    // From an implementation point of view, a set is equivalent to a
-    // sequence.
-    readEndSequence();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public int readEnumerated() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if ((peekLength < 1) || (peekLength > 4))
-    {
-      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
-          .get(peekLength);
-      throw DecodeException.fatalError(message);
-    }
-
-    // From an implementation point of view, an enumerated value is
-    // equivalent to an integer.
-    return (int) readInteger();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public long readInteger() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if ((peekLength < 1) || (peekLength > 8))
-    {
-      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
-          .get(peekLength);
-      throw DecodeException.fatalError(message);
-    }
-
-    readLimiter.checkLimit(peekLength);
-    if (peekLength > 4)
-    {
-      long longValue = 0;
-      for (int i = 0; i < peekLength; i++)
-      {
-        final int readByte = buffer.get();
-        if ((i == 0) && (((byte) readByte) < 0))
-        {
-          longValue = 0xFFFFFFFFFFFFFFFFL;
+            bytesRead += readSize;
         }
-        longValue = (longValue << 8) | (readByte & 0xFF);
-      }
 
-      state = ELEMENT_READ_STATE_NEED_TYPE;
-      return longValue;
-    }
-    else
-    {
-      int intValue = 0;
-      for (int i = 0; i < peekLength; i++)
-      {
-        final int readByte = buffer.get();
-        if ((i == 0) && (((byte) readByte) < 0))
-        {
-          intValue = 0xFFFFFFFF;
+        public SequenceLimiter endSequence() throws IOException {
+            parent.checkLimit(remaining());
+
+            if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE) && remaining() > 0) {
+                StaticUtils.DEBUG_LOG.fine(String.format(
+                        "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE", remaining()));
+            }
+
+            for (int i = 0; i < remaining(); i++) {
+                buffer.get();
+            }
+
+            return parent;
         }
-        intValue = (intValue << 8) | (readByte & 0xFF);
-      }
 
-      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-      {
-        StaticUtils.DEBUG_LOG.finest(String.format(
-            "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", peekType,
-            peekLength, intValue));
-      }
+        public int remaining() {
+            return readLimit - bytesRead;
+        }
 
-      state = ELEMENT_READ_STATE_NEED_TYPE;
-      return intValue;
-    }
-  }
+        public ChildSequenceLimiter startSequence(final int readLimit) {
+            if (child == null) {
+                child = new ChildSequenceLimiter();
+                child.parent = this;
+            }
 
+            child.readLimit = readLimit;
+            child.bytesRead = 0;
 
-
-  /**
-   * {@inheritDoc}
-   */
-  public void readNull() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    // Make sure that the decoded length is exactly zero byte.
-    if (peekLength != 0)
-    {
-      final LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH
-          .get(peekLength);
-      throw DecodeException.fatalError(message);
+            return child;
+        }
     }
 
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 NULL(type=0x%x, length=%d)", peekType, peekLength));
+    private final class RootSequenceLimiter implements SequenceLimiter {
+        private ChildSequenceLimiter child;
+
+        public void checkLimit(final int readSize) throws IOException {
+            if (buffer.remaining() < readSize) {
+                final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+                throw DecodeException.fatalError(message);
+            }
+        }
+
+        public ChildSequenceLimiter endSequence() throws DecodeException {
+            final LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED.get();
+            throw new IllegalStateException(message.toString());
+        }
+
+        public int remaining() {
+            return buffer.remaining();
+        }
+
+        public ChildSequenceLimiter startSequence(final int readLimit) {
+            if (child == null) {
+                child = new ChildSequenceLimiter();
+                child.parent = this;
+            }
+
+            child.readLimit = readLimit;
+            child.bytesRead = 0;
+
+            return child;
+        }
     }
 
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-  }
+    private interface SequenceLimiter {
+        public void checkLimit(int readSize) throws IOException;
 
+        public SequenceLimiter endSequence() throws IOException;
 
+        public int remaining();
 
-  /**
-   * {@inheritDoc}
-   */
-  public ByteString readOctetString() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if (peekLength == 0)
-    {
-      state = ELEMENT_READ_STATE_NEED_TYPE;
-      return ByteString.empty();
+        public SequenceLimiter startSequence(int readLimit);
     }
 
-    readLimiter.checkLimit(peekLength);
-    // Copy the value and construct the element to return.
-    final byte[] value = new byte[peekLength];
-    buffer.get(value);
+    private static final int MAX_STRING_BUFFER_SIZE = 1024;
 
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG
-          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
-              peekType, peekLength));
+    private int state = ELEMENT_READ_STATE_NEED_TYPE;
+
+    private byte peekType = 0;
+
+    private int peekLength = -1;
+
+    private int lengthBytesNeeded = 0;
+
+    private final int maxElementSize;
+
+    private final CompositeBuffer buffer;
+
+    private SequenceLimiter readLimiter;
+
+    private final byte[] stringBuffer;
+
+    /**
+     * Creates a new ASN1 reader whose source is the provided input stream and
+     * having a user defined maximum BER element size.
+     *
+     * @param maxElementSize
+     *            The maximum BER element size, or <code>0</code> to indicate
+     *            that there is no limit.
+     * @param memoryManager
+     *            The memory manager to use for buffering.
+     */
+    ASN1BufferReader(final int maxElementSize, final MemoryManager<?> memoryManager) {
+        this.readLimiter = new RootSequenceLimiter();
+        this.stringBuffer = new byte[MAX_STRING_BUFFER_SIZE];
+        this.maxElementSize = maxElementSize;
+        this.buffer = BuffersBuffer.create(memoryManager);
     }
 
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-    return ByteString.wrap(value);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public ByteStringBuilder readOctetString(final ByteStringBuilder builder)
-      throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if (peekLength == 0)
-    {
-      state = ELEMENT_READ_STATE_NEED_TYPE;
-      return builder;
+    /**
+     * Closes this ASN.1 reader and the underlying stream.
+     *
+     * @throws IOException
+     *             if an I/O error occurs
+     */
+    public void close() throws IOException {
+        buffer.dispose();
     }
 
-    readLimiter.checkLimit(peekLength);
-    // Copy the value and construct the element to return.
-    // TODO: Is there a more efficient way to do this?
-    for (int i = 0; i < peekLength; i++)
-    {
-      builder.append(buffer.get());
+    /**
+     * Determines if a complete ASN.1 element is ready to be read from the
+     * stream reader.
+     *
+     * @return <code>true</code> if another complete element is available or
+     *         <code>false</code> otherwise.
+     * @throws IOException
+     *             If an error occurs while trying to decode an ASN1 element.
+     */
+    public boolean elementAvailable() throws IOException {
+        return !((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(true))
+                && !((state == ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE)
+                        && !needFirstLengthByteState(true))
+                && !((state == ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES)
+                        && !needAdditionalLengthBytesState(true))
+                && peekLength <= readLimiter.remaining();
+
     }
 
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG
-          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
-              peekType, peekLength));
+    /**
+     * Determines if the input stream contains at least one ASN.1 element to be
+     * read.
+     *
+     * @return <code>true</code> if another element is available or
+     *         <code>false</code> otherwise.
+     * @throws IOException
+     *             If an error occurs while trying to decode an ASN1 element.
+     */
+    public boolean hasNextElement() throws IOException {
+        return (state != ELEMENT_READ_STATE_NEED_TYPE) || needTypeState(true);
     }
 
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-    return builder;
-  }
+    /**
+     * {@inheritDoc}
+     */
+    public int peekLength() throws IOException {
+        peekType();
 
+        switch (state) {
+        case ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE:
+            needFirstLengthByteState(false);
+            break;
 
+        case ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES:
+            needAdditionalLengthBytesState(false);
+        }
 
-  /**
-   * {@inheritDoc}
-   */
-  public String readOctetStringAsString() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    if (peekLength == 0)
-    {
-      state = ELEMENT_READ_STATE_NEED_TYPE;
-      return "";
+        return peekLength;
     }
 
-    byte[] readBuffer;
-    if (peekLength <= stringBuffer.length)
-    {
-      readBuffer = stringBuffer;
-    }
-    else
-    {
-      readBuffer = new byte[peekLength];
+    /**
+     * {@inheritDoc}
+     */
+    public byte peekType() throws IOException {
+        if (state == ELEMENT_READ_STATE_NEED_TYPE) {
+            needTypeState(false);
+        }
+
+        return peekType;
     }
 
-    readLimiter.checkLimit(peekLength);
-    buffer.get(readBuffer, 0, peekLength);
+    /**
+     * {@inheritDoc}
+     */
+    public boolean readBoolean() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
 
-    state = ELEMENT_READ_STATE_NEED_TYPE;
+        if (peekLength != 1) {
+            final LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH.get(peekLength);
+            throw DecodeException.fatalError(message);
+        }
 
-    String str;
-    try
-    {
-      str = new String(readBuffer, 0, peekLength, "UTF-8");
-    }
-    catch (final Exception e)
-    {
-      if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
-      {
-        StaticUtils.DEBUG_LOG
-            .warning("Unable to decode ASN.1 OCTETSTRING bytes as UTF-8 string: "
-                + e.toString());
-      }
+        readLimiter.checkLimit(peekLength);
+        final byte readByte = buffer.get();
 
-      str = new String(stringBuffer, 0, peekLength);
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                    "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", peekType, peekLength,
+                    String.valueOf(readByte != 0x00)));
+        }
+
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+        return readByte != 0x00;
     }
 
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)", peekType,
-          peekLength, str));
+    /**
+     * {@inheritDoc}
+     */
+    public void readEndSequence() throws IOException {
+        readLimiter = readLimiter.endSequence();
+
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format("READ ASN.1 END SEQUENCE"));
+        }
+
+        // Reset the state
+        state = ELEMENT_READ_STATE_NEED_TYPE;
     }
 
-    return str;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void readStartSequence() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    readLimiter = readLimiter.startSequence(peekLength);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 START SEQUENCE(type=0x%x, length=%d)", peekType,
-          peekLength));
+    /**
+     * {@inheritDoc}
+     */
+    public void readEndSet() throws IOException {
+        // From an implementation point of view, a set is equivalent to a
+        // sequence.
+        readEndSequence();
     }
 
-    // Reset the state
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-  }
+    /**
+     * {@inheritDoc}
+     */
+    public int readEnumerated() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
 
+        if ((peekLength < 1) || (peekLength > 4)) {
+            final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+            throw DecodeException.fatalError(message);
+        }
 
-
-  /**
-   * {@inheritDoc}
-   */
-  public void readStartSet() throws IOException
-  {
-    // From an implementation point of view, a set is equivalent to a
-    // sequence.
-    readStartSequence();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public ASN1Reader skipElement() throws IOException
-  {
-    // Read the header if haven't done so already
-    peekLength();
-
-    readLimiter.checkLimit(peekLength);
-    for (int i = 0; i < peekLength; i++)
-    {
-      buffer.get();
-    }
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-    return this;
-  }
-
-
-
-  void appendBytesRead(final Buffer buffer)
-  {
-    this.buffer.append(buffer);
-  }
-
-
-
-  void disposeBytesRead()
-  {
-    this.buffer.shrink();
-  }
-
-
-
-  /**
-   * Internal helper method reading the additional ASN.1 length bytes and
-   * transition to the next state if successful.
-   *
-   * @param ensureRead
-   *          <code>true</code> to check for availability first.
-   * @return <code>true</code> if the length bytes was successfully read.
-   * @throws IOException
-   *           If an error occurs while reading from the stream.
-   */
-  private boolean needAdditionalLengthBytesState(final boolean ensureRead)
-      throws IOException
-  {
-    if (ensureRead && (readLimiter.remaining() < lengthBytesNeeded))
-    {
-      return false;
+        // From an implementation point of view, an enumerated value is
+        // equivalent to an integer.
+        return (int) readInteger();
     }
 
-    byte readByte;
-    readLimiter.checkLimit(lengthBytesNeeded);
-    while (lengthBytesNeeded > 0)
-    {
-      readByte = buffer.get();
-      peekLength = (peekLength << 8) | (readByte & 0xFF);
-      lengthBytesNeeded--;
+    /**
+     * {@inheritDoc}
+     */
+    public long readInteger() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
+
+        if ((peekLength < 1) || (peekLength > 8)) {
+            final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+            throw DecodeException.fatalError(message);
+        }
+
+        readLimiter.checkLimit(peekLength);
+        if (peekLength > 4) {
+            long longValue = 0;
+            for (int i = 0; i < peekLength; i++) {
+                final int readByte = buffer.get();
+                if ((i == 0) && (((byte) readByte) < 0)) {
+                    longValue = 0xFFFFFFFFFFFFFFFFL;
+                }
+                longValue = (longValue << 8) | (readByte & 0xFF);
+            }
+
+            state = ELEMENT_READ_STATE_NEED_TYPE;
+            return longValue;
+        } else {
+            int intValue = 0;
+            for (int i = 0; i < peekLength; i++) {
+                final int readByte = buffer.get();
+                if ((i == 0) && (((byte) readByte) < 0)) {
+                    intValue = 0xFFFFFFFF;
+                }
+                intValue = (intValue << 8) | (readByte & 0xFF);
+            }
+
+            if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+                StaticUtils.DEBUG_LOG.finest(String.format(
+                        "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", peekType, peekLength,
+                        intValue));
+            }
+
+            state = ELEMENT_READ_STATE_NEED_TYPE;
+            return intValue;
+        }
     }
 
-    // Make sure that the element is not larger than the maximum allowed
-    // message size.
-    if ((maxElementSize > 0) && (peekLength > maxElementSize))
-    {
-      final LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
-          .get(peekLength, maxElementSize);
-      throw DecodeException.fatalError(m);
-    }
-    state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
-    return true;
-  }
+    /**
+     * {@inheritDoc}
+     */
+    public void readNull() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
 
+        // Make sure that the decoded length is exactly zero byte.
+        if (peekLength != 0) {
+            final LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH.get(peekLength);
+            throw DecodeException.fatalError(message);
+        }
 
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format("READ ASN.1 NULL(type=0x%x, length=%d)",
+                    peekType, peekLength));
+        }
 
-  /**
-   * Internal helper method reading the first length bytes and transition to the
-   * next state if successful.
-   *
-   * @param ensureRead
-   *          <code>true</code> to check for availability first.
-   * @return <code>true</code> if the length bytes was successfully read
-   * @throws IOException
-   *           If an error occurs while trying to decode an ASN1 element.
-   */
-  private boolean needFirstLengthByteState(final boolean ensureRead)
-      throws IOException
-  {
-    if (ensureRead && (readLimiter.remaining() <= 0))
-    {
-      return false;
+        state = ELEMENT_READ_STATE_NEED_TYPE;
     }
 
-    readLimiter.checkLimit(1);
-    byte readByte = buffer.get();
-    peekLength = (readByte & 0x7F);
-    if (peekLength != readByte)
-    {
-      lengthBytesNeeded = peekLength;
-      if (lengthBytesNeeded > 4)
-      {
-        final LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
-            .get(lengthBytesNeeded);
-        throw DecodeException.fatalError(message);
-      }
-      peekLength = 0x00;
+    /**
+     * {@inheritDoc}
+     */
+    public ByteString readOctetString() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
 
-      if (ensureRead && (readLimiter.remaining() < lengthBytesNeeded))
-      {
-        state = ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
-        return false;
-      }
+        if (peekLength == 0) {
+            state = ELEMENT_READ_STATE_NEED_TYPE;
+            return ByteString.empty();
+        }
 
-      readLimiter.checkLimit(lengthBytesNeeded);
-      while (lengthBytesNeeded > 0)
-      {
-        readByte = buffer.get();
-        peekLength = (peekLength << 8) | (readByte & 0xFF);
-        lengthBytesNeeded--;
-      }
+        readLimiter.checkLimit(peekLength);
+        // Copy the value and construct the element to return.
+        final byte[] value = new byte[peekLength];
+        buffer.get(value);
+
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                    "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType, peekLength));
+        }
+
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+        return ByteString.wrap(value);
     }
 
-    // Make sure that the element is not larger than the maximum allowed
-    // message size.
-    if ((maxElementSize > 0) && (peekLength > maxElementSize))
-    {
-      final LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
-          .get(peekLength, maxElementSize);
-      throw DecodeException.fatalError(m);
-    }
-    state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
-    return true;
-  }
+    /**
+     * {@inheritDoc}
+     */
+    public ByteStringBuilder readOctetString(final ByteStringBuilder builder) throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
 
+        if (peekLength == 0) {
+            state = ELEMENT_READ_STATE_NEED_TYPE;
+            return builder;
+        }
 
+        readLimiter.checkLimit(peekLength);
+        // Copy the value and construct the element to return.
+        // TODO: Is there a more efficient way to do this?
+        for (int i = 0; i < peekLength; i++) {
+            builder.append(buffer.get());
+        }
 
-  /**
-   * Internal helper method reading the ASN.1 type byte and transition to the
-   * next state if successful.
-   *
-   * @param ensureRead
-   *          <code>true</code> to check for availability first.
-   * @return <code>true</code> if the type byte was successfully read
-   * @throws IOException
-   *           If an error occurs while trying to decode an ASN1 element.
-   */
-  private boolean needTypeState(final boolean ensureRead) throws IOException
-  {
-    // Read just the type.
-    if (ensureRead && (readLimiter.remaining() <= 0))
-    {
-      return false;
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                    "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType, peekLength));
+        }
+
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+        return builder;
     }
 
-    readLimiter.checkLimit(1);
-    peekType = buffer.get();
-    state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
-    return true;
-  }
+    /**
+     * {@inheritDoc}
+     */
+    public String readOctetStringAsString() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
+
+        if (peekLength == 0) {
+            state = ELEMENT_READ_STATE_NEED_TYPE;
+            return "";
+        }
+
+        byte[] readBuffer;
+        if (peekLength <= stringBuffer.length) {
+            readBuffer = stringBuffer;
+        } else {
+            readBuffer = new byte[peekLength];
+        }
+
+        readLimiter.checkLimit(peekLength);
+        buffer.get(readBuffer, 0, peekLength);
+
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+
+        String str;
+        try {
+            str = new String(readBuffer, 0, peekLength, "UTF-8");
+        } catch (final Exception e) {
+            if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING)) {
+                StaticUtils.DEBUG_LOG
+                        .warning("Unable to decode ASN.1 OCTETSTRING bytes as UTF-8 string: "
+                                + e.toString());
+            }
+
+            str = new String(stringBuffer, 0, peekLength);
+        }
+
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                    "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)", peekType, peekLength,
+                    str));
+        }
+
+        return str;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void readStartSequence() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
+
+        readLimiter = readLimiter.startSequence(peekLength);
+
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST)) {
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                    "READ ASN.1 START SEQUENCE(type=0x%x, length=%d)", peekType, peekLength));
+        }
+
+        // Reset the state
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void readStartSet() throws IOException {
+        // From an implementation point of view, a set is equivalent to a
+        // sequence.
+        readStartSequence();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ASN1Reader skipElement() throws IOException {
+        // Read the header if haven't done so already
+        peekLength();
+
+        readLimiter.checkLimit(peekLength);
+        for (int i = 0; i < peekLength; i++) {
+            buffer.get();
+        }
+        state = ELEMENT_READ_STATE_NEED_TYPE;
+        return this;
+    }
+
+    void appendBytesRead(final Buffer buffer) {
+        this.buffer.append(buffer);
+    }
+
+    void disposeBytesRead() {
+        this.buffer.shrink();
+    }
+
+    /**
+     * Internal helper method reading the additional ASN.1 length bytes and
+     * transition to the next state if successful.
+     *
+     * @param ensureRead
+     *            <code>true</code> to check for availability first.
+     * @return <code>true</code> if the length bytes was successfully read.
+     * @throws IOException
+     *             If an error occurs while reading from the stream.
+     */
+    private boolean needAdditionalLengthBytesState(final boolean ensureRead) throws IOException {
+        if (ensureRead && (readLimiter.remaining() < lengthBytesNeeded)) {
+            return false;
+        }
+
+        byte readByte;
+        readLimiter.checkLimit(lengthBytesNeeded);
+        while (lengthBytesNeeded > 0) {
+            readByte = buffer.get();
+            peekLength = (peekLength << 8) | (readByte & 0xFF);
+            lengthBytesNeeded--;
+        }
+
+        // Make sure that the element is not larger than the maximum allowed
+        // message size.
+        if ((maxElementSize > 0) && (peekLength > maxElementSize)) {
+            final LocalizableMessage m =
+                    ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+                            .get(peekLength, maxElementSize);
+            throw DecodeException.fatalError(m);
+        }
+        state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
+        return true;
+    }
+
+    /**
+     * Internal helper method reading the first length bytes and transition to
+     * the next state if successful.
+     *
+     * @param ensureRead
+     *            <code>true</code> to check for availability first.
+     * @return <code>true</code> if the length bytes was successfully read
+     * @throws IOException
+     *             If an error occurs while trying to decode an ASN1 element.
+     */
+    private boolean needFirstLengthByteState(final boolean ensureRead) throws IOException {
+        if (ensureRead && (readLimiter.remaining() <= 0)) {
+            return false;
+        }
+
+        readLimiter.checkLimit(1);
+        byte readByte = buffer.get();
+        peekLength = (readByte & 0x7F);
+        if (peekLength != readByte) {
+            lengthBytesNeeded = peekLength;
+            if (lengthBytesNeeded > 4) {
+                final LocalizableMessage message =
+                        ERR_ASN1_INVALID_NUM_LENGTH_BYTES.get(lengthBytesNeeded);
+                throw DecodeException.fatalError(message);
+            }
+            peekLength = 0x00;
+
+            if (ensureRead && (readLimiter.remaining() < lengthBytesNeeded)) {
+                state = ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
+                return false;
+            }
+
+            readLimiter.checkLimit(lengthBytesNeeded);
+            while (lengthBytesNeeded > 0) {
+                readByte = buffer.get();
+                peekLength = (peekLength << 8) | (readByte & 0xFF);
+                lengthBytesNeeded--;
+            }
+        }
+
+        // Make sure that the element is not larger than the maximum allowed
+        // message size.
+        if ((maxElementSize > 0) && (peekLength > maxElementSize)) {
+            final LocalizableMessage m =
+                    ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+                            .get(peekLength, maxElementSize);
+            throw DecodeException.fatalError(m);
+        }
+        state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
+        return true;
+    }
+
+    /**
+     * Internal helper method reading the ASN.1 type byte and transition to the
+     * next state if successful.
+     *
+     * @param ensureRead
+     *            <code>true</code> to check for availability first.
+     * @return <code>true</code> if the type byte was successfully read
+     * @throws IOException
+     *             If an error occurs while trying to decode an ASN1 element.
+     */
+    private boolean needTypeState(final boolean ensureRead) throws IOException {
+        // Read just the type.
+        if (ensureRead && (readLimiter.remaining() <= 0)) {
+            return false;
+        }
+
+        readLimiter.checkLimit(1);
+        peekType = buffer.get();
+        state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
+        return true;
+    }
 }

--
Gitblit v1.10.0