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

Jean-Noel Rouvignac
04.53.2014 8dc526607c7fa09081a3939f27cddc07d01809fa
OPENDJ-1307 Migrate server ASN1 classes to SDK

Code review: Matthew Swift

Preparation work to allow opendj3-server-dev branch to use the SDK ASN1 types.

ASN1.java:
Added UNIVERSAL_BIT_STRING_TYPE.
Reordered the UNIVERSAL_* fields.
Made a few TYPE_MASK_* public.
Added getWriter(ByteStringBuilder, int maxBufferSize)
Added getWriter(OutputStream, int maxBufferSize)

ASN1Reader.java, ASN1*Reader:
Added readEndExplicitTag() and readStartExplicitTag().

ASN1OutputStreamWriter.java, ASN1OutputStreamWriterTestCase.java:
Changed ASN1OutputStreamWriter(OutputStream) to ASN1OutputStreamWriter(OutputStream, int maxBufferSize) + updated the test.
Added maxBufferSize field and used it in writeEndSequence().
7 files modified
152 ■■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java 61 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1ByteSequenceReader.java 12 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1InputStreamReader.java 12 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java 28 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1Reader.java 25 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/io/ASN1OutputStreamWriterTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java 12 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java
@@ -45,6 +45,12 @@
public final class ASN1 {
    /**
     * Maximum buffer size when reading ASN1. Buffers above this threshold will
     * be discarded for garbage collection to avoid OutOfMemoryErrors.
     */
    private static final int DEFAULT_MAX_BUFFER_SIZE = 32 * 1024;
    /**
     * The byte array containing the pre-encoded ASN.1 encoding for a boolean
     * value of "false".
     */
@@ -62,14 +68,18 @@
    public static final byte UNIVERSAL_BOOLEAN_TYPE = 0x01;
    /**
     * The BER type that is assigned to the universal enumerated type.
     */
    public static final byte UNIVERSAL_ENUMERATED_TYPE = 0x0A;
    /**
     * The BER type that is assigned to the universal integer type.
     */
    public static final byte UNIVERSAL_INTEGER_TYPE = 0x02;
    /**
     * The BER type that is assigned to the universal bit string type.
     */
    public static final byte UNIVERSAL_BIT_STRING_TYPE = 0x03;
    /**
     * The BER type that is assigned to the universal octet string type.
     */
    public static final byte UNIVERSAL_OCTET_STRING_TYPE = 0x04;
    /**
     * The BER type that is assigned to the universal null type.
@@ -77,9 +87,9 @@
    public static final byte UNIVERSAL_NULL_TYPE = 0x05;
    /**
     * The BER type that is assigned to the universal octet string type.
     * The BER type that is assigned to the universal enumerated type.
     */
    public static final byte UNIVERSAL_OCTET_STRING_TYPE = 0x04;
    public static final byte UNIVERSAL_ENUMERATED_TYPE = 0x0A;
    /**
     * The BER type that is assigned to the universal sequence type.
@@ -139,12 +149,12 @@
     * The bitmask that can be ANDed with the BER type to determine if the
     * element is constructed.
     */
    static final byte TYPE_MASK_CONSTRUCTED = 0x20;
    public static final byte TYPE_MASK_CONSTRUCTED = 0x20;
    /**
     * The bitmask that can be ANDed with the BER type to determine if the
     * element is in the context-specific class.
     */
    static final byte TYPE_MASK_CONTEXT = (byte) 0x80;
    public static final byte TYPE_MASK_CONTEXT = (byte) 0x80;
    /**
     * The bitmask that can be ANDed with the BER type to determine if the
     * element is a primitive.
@@ -278,7 +288,22 @@
     * @return The new ASN.1 writer.
     */
    public static ASN1Writer getWriter(final ByteStringBuilder builder) {
        return getWriter(builder.asOutputStream());
        return getWriter(builder.asOutputStream(), DEFAULT_MAX_BUFFER_SIZE);
    }
    /**
     * Returns an ASN.1 writer whose destination is the provided byte string
     * builder.
     *
     * @param builder
     *            The output stream to use.
     * @param maxBufferSize
     *          The threshold capacity beyond which internal cached buffers used
     *          for encoding and decoding ASN1 will be trimmed after use.
     * @return The new ASN.1 writer.
     */
    public static ASN1Writer getWriter(final ByteStringBuilder builder, final int maxBufferSize) {
        return getWriter(builder.asOutputStream(), maxBufferSize);
    }
    /**
@@ -289,7 +314,21 @@
     * @return The new ASN.1 writer.
     */
    public static ASN1Writer getWriter(final OutputStream stream) {
        return new ASN1OutputStreamWriter(stream);
        return getWriter(stream, DEFAULT_MAX_BUFFER_SIZE);
    }
    /**
     * Returns an ASN.1 writer whose destination is the provided output stream.
     *
     * @param stream
     *            The output stream to use.
     * @param maxBufferSize
     *          The threshold capacity beyond which internal cached buffers used
     *          for encoding and decoding ASN1 will be trimmed after use.
     * @return The new ASN.1 writer.
     */
    public static ASN1Writer getWriter(final OutputStream stream, final int maxBufferSize) {
        return new ASN1OutputStreamWriter(stream, maxBufferSize);
    }
    // Prevent instantiation.
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1ByteSequenceReader.java
@@ -174,6 +174,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readEndExplicitTag() throws DecodeException, IOException {
        readEndSequence();
    }
    /**
     * {@inheritDoc}
     */
@@ -333,6 +339,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readStartExplicitTag() throws DecodeException, IOException {
        readStartSequence();
    }
    /**
     * {@inheritDoc}
     */
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1InputStreamReader.java
@@ -206,6 +206,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readEndExplicitTag() throws DecodeException, IOException {
        readEndSequence();
    }
    /**
     * {@inheritDoc}
     */
@@ -429,6 +435,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readStartExplicitTag() throws DecodeException, IOException {
        readStartSequence();
    }
    /**
     * {@inheritDoc}
     */
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java
@@ -42,21 +42,26 @@
/**
 * An ASN1Writer implementation that outputs to an outputstream.
 */
final class ASN1OutputStreamWriter extends AbstractASN1Writer implements ASN1Writer {
final class ASN1OutputStreamWriter extends AbstractASN1Writer {
    private final OutputStream rootStream;
    private OutputStream out;
    private final ArrayList<ByteStringBuilder> streamStack;
    private int stackDepth;
    private final int maxBufferSize;
    /**
     * Creates a new ASN.1 output stream reader.
     *
     * @param stream
     *            The underlying output stream.
     * @param maxBufferSize
     *          The threshold capacity beyond which internal cached buffers used
     *          for encoding and decoding ASN1 will be trimmed after use.
     */
    ASN1OutputStreamWriter(final OutputStream stream) {
    ASN1OutputStreamWriter(final OutputStream stream, final int maxBufferSize) {
        this.out = stream;
        this.rootStream = stream;
        this.maxBufferSize = maxBufferSize;
        this.streamStack = new ArrayList<ByteStringBuilder>();
        this.stackDepth = -1;
    }
@@ -64,6 +69,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
        while (stackDepth >= 0) {
            writeEndSequence();
@@ -76,6 +82,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public void flush() throws IOException {
        rootStream.flush();
    }
@@ -83,6 +90,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeBoolean(final byte type, final boolean booleanValue) throws IOException {
        out.write(type);
        writeLength(1);
@@ -96,6 +104,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeEndSequence() throws IOException {
        if (stackDepth < 0) {
            final LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED.get();
@@ -118,13 +127,19 @@
        IO_LOG.trace("WRITE ASN.1 END SEQUENCE(length={})", childStream.length());
        if (childStream.capacity() > maxBufferSize) {
            // garbage collect excessively large buffers
            childStream.clear(maxBufferSize);
        } else {
        childStream.clear();
        }
        return this;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeEndSet() throws IOException {
        return writeEndSequence();
    }
@@ -132,6 +147,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeEnumerated(final byte type, final int intValue) throws IOException {
        return writeInteger(type, intValue);
    }
@@ -139,6 +155,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeInteger(final byte type, final int intValue) throws IOException {
        out.write(type);
        if (((intValue < 0) && ((intValue & 0xFFFFFF80) == 0xFFFFFF80))
@@ -173,6 +190,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeInteger(final byte type, final long longValue) throws IOException {
        out.write(type);
        if (((longValue < 0) && ((longValue & 0xFFFFFFFFFFFFFF80L) == 0xFFFFFFFFFFFFFF80L))
@@ -249,6 +267,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeNull(final byte type) throws IOException {
        out.write(type);
        writeLength(0);
@@ -260,6 +279,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeOctetString(final byte type, final byte[] value, final int offset,
            final int length) throws IOException {
        out.write(type);
@@ -273,6 +293,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeOctetString(final byte type, final ByteSequence value)
            throws IOException {
        out.write(type);
@@ -287,6 +308,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeOctetString(final byte type, final String value) throws IOException {
        out.write(type);
@@ -307,6 +329,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeStartSequence(final byte type) throws IOException {
        // Write the type in current stream switch to next sub-stream
        out.write(type);
@@ -330,6 +353,7 @@
    /**
     * {@inheritDoc}
     */
    @Override
    public ASN1Writer writeStartSet(final byte type) throws IOException {
        // From an implementation point of view, a set is equivalent to a
        // sequence.
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1Reader.java
@@ -144,6 +144,19 @@
    void readEndSequence() throws DecodeException, IOException;
    /**
     * Finishes reading an explicit tag and discards any unread elements.
     *
     * @throws DecodeException
     *             If an error occurs while advancing to the end of the
     *             explicit tag.
     * @throws IOException
     *             If an unexpected IO error occurred.
     * @throws IllegalStateException
     *             If there is no explicit tag being read.
     */
    void readEndExplicitTag() throws DecodeException, IOException;
    /**
     * Finishes reading a set and discards any unread elements.
     *
     * @throws DecodeException
@@ -325,6 +338,18 @@
    void readStartSequence() throws DecodeException, IOException;
    /**
     * Reads the next element as an explicit tag having the Universal Sequence
     * ASN.1 type tag. All further reads will read the elements in the explicit
     * tag until {@link #readEndExplicitTag()} is called.
     *
     * @throws DecodeException
     *             If the element cannot be decoded as an explicit tag.
     * @throws IOException
     *             If an unexpected IO error occurred.
     */
    void readStartExplicitTag() throws DecodeException, IOException;
    /**
     * Reads the next element as a sequence having the provided type tag. All
     * further reads will read the elements in the sequence until
     * {@link #readEndSequence()} is called.
opendj-core/src/test/java/org/forgerock/opendj/io/ASN1OutputStreamWriterTestCase.java
@@ -34,7 +34,7 @@
 */
public class ASN1OutputStreamWriterTestCase extends ASN1WriterTestCase {
    private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    private final ASN1Writer writer = new ASN1OutputStreamWriter(outStream);
    private final ASN1Writer writer = new ASN1OutputStreamWriter(outStream, 1);
    @Override
    protected byte[] getEncodedBytes() {
opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java
@@ -269,6 +269,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readEndExplicitTag() throws DecodeException, IOException {
        readEndSequence();
    }
    /**
     * {@inheritDoc}
     */
@@ -462,6 +468,12 @@
        state = ASN1.ELEMENT_READ_STATE_NEED_TYPE;
    }
    /** {@inheritDoc} */
    @Override
    public void readStartExplicitTag() throws DecodeException, IOException {
        readStartSequence();
    }
    /**
     * {@inheritDoc}
     */