From f21d49179409cc1f7089e08d6ad1596bfd4de47f Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Wed, 08 Jan 2014 18:37:25 +0000
Subject: [PATCH] Facilitate compression and cryptographic operations to/from byte strings:
---
/dev/null | 113 ----------------------------
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java | 7 -
opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java | 31 +++++++
opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java | 38 +++++++++
opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java | 25 ++---
5 files changed, 82 insertions(+), 132 deletions(-)
diff --git a/opendj-core/src/main/java/com/forgerock/opendj/util/ByteSequenceOutputStream.java b/opendj-core/src/main/java/com/forgerock/opendj/util/ByteSequenceOutputStream.java
deleted file mode 100644
index b7fb85c..0000000
--- a/opendj-core/src/main/java/com/forgerock/opendj/util/ByteSequenceOutputStream.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * 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 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
- *
- *
- * Copyright 2006-2008 Sun Microsystems, Inc.
- */
-package com.forgerock.opendj.util;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.forgerock.opendj.ldap.ByteStringBuilder;
-
-/**
- * An adapter class that allows writing to an byte string builder with the
- * outputstream interface.
- */
-public final class ByteSequenceOutputStream extends OutputStream {
-
- private final ByteStringBuilder buffer;
-
- /**
- * Creates a new byte string builder output stream.
- *
- * @param buffer
- * The underlying byte string builder.
- */
- public ByteSequenceOutputStream(final ByteStringBuilder buffer) {
- this.buffer = buffer;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void close() throws IOException {
- buffer.clear();
- }
-
- /**
- * Gets the length of the underlying byte string builder.
- *
- * @return The length of the underlying byte string builder.
- */
- public int length() {
- return buffer.length();
- }
-
- /**
- * Resets this output stream such that the underlying byte string builder is
- * empty.
- */
- public void reset() {
- buffer.clear();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void write(final byte[] bytes) throws IOException {
- buffer.append(bytes);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void write(final byte[] bytes, final int i, final int i1) throws IOException {
- buffer.append(bytes, i, i1);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void write(final int i) throws IOException {
- buffer.append(((byte) (i & 0xFF)));
- }
-
- /**
- * Writes the content of the underlying byte string builder to the provided
- * output stream.
- *
- * @param stream
- * The output stream.
- * @throws IOException
- * If an I/O error occurs. In particular, an {@code IOException}
- * is thrown if the output stream is closed.
- */
- public void writeTo(final OutputStream stream) throws IOException {
- buffer.copyTo(stream);
- }
-}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java b/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java
index db4b585..9ab3ea8 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
- * Portions copyright 2012-2013 ForgeRock AS.
+ * Portions copyright 2012-2014 ForgeRock AS.
*/
package org.forgerock.opendj.io;
@@ -35,8 +35,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteStringBuilder;
-import com.forgerock.opendj.util.ByteSequenceOutputStream;
-
/**
* This class contains various static factory methods for creating ASN.1 readers
* and writers.
@@ -280,8 +278,7 @@
* @return The new ASN.1 writer.
*/
public static ASN1Writer getWriter(final ByteStringBuilder builder) {
- final ByteSequenceOutputStream outputStream = new ByteSequenceOutputStream(builder);
- return getWriter(outputStream);
+ return getWriter(builder.asOutputStream());
}
/**
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java b/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java
index 35943c5..c09f906 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
- * Portions copyright 2012-2013 ForgeRock AS.
+ * Portions copyright 2012-2014 ForgeRock AS.
*/
package org.forgerock.opendj.io;
@@ -37,7 +37,6 @@
import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteStringBuilder;
-import com.forgerock.opendj.util.ByteSequenceOutputStream;
import com.forgerock.opendj.util.StaticUtils;
/**
@@ -46,7 +45,7 @@
final class ASN1OutputStreamWriter extends AbstractASN1Writer implements ASN1Writer {
private final OutputStream rootStream;
private OutputStream out;
- private final ArrayList<ByteSequenceOutputStream> streamStack;
+ private final ArrayList<ByteStringBuilder> streamStack;
private int stackDepth;
/**
@@ -58,7 +57,7 @@
ASN1OutputStreamWriter(final OutputStream stream) {
this.out = stream;
this.rootStream = stream;
- this.streamStack = new ArrayList<ByteSequenceOutputStream>();
+ this.streamStack = new ArrayList<ByteStringBuilder>();
this.stackDepth = -1;
}
@@ -70,7 +69,6 @@
writeEndSequence();
}
rootStream.flush();
-
streamStack.clear();
rootStream.close();
}
@@ -104,23 +102,23 @@
throw new IllegalStateException(message.toString());
}
- final ByteSequenceOutputStream childStream = streamStack.get(stackDepth);
+ final ByteStringBuilder childStream = streamStack.get(stackDepth);
// Decrement the stack depth and get the parent stream
--stackDepth;
-
- final OutputStream parentStream = stackDepth < 0 ? rootStream : streamStack.get(stackDepth);
+ final OutputStream parentStream =
+ stackDepth < 0 ? rootStream : streamStack.get(stackDepth).asOutputStream();
// Switch to parent stream and reset the sub-stream
out = parentStream;
// Write the length and contents of the sub-stream
writeLength(childStream.length());
- childStream.writeTo(parentStream);
+ childStream.copyTo(parentStream);
IO_LOG.trace("WRITE ASN.1 END SEQUENCE(length={})", childStream.length());
- childStream.reset();
+ childStream.clear();
return this;
}
@@ -318,12 +316,11 @@
// Make sure we have a cached sub-stream at this depth
if (stackDepth >= streamStack.size()) {
- final ByteSequenceOutputStream subStream =
- new ByteSequenceOutputStream(new ByteStringBuilder());
+ final ByteStringBuilder subStream = new ByteStringBuilder();
streamStack.add(subStream);
- out = subStream;
+ out = subStream.asOutputStream();
} else {
- out = streamStack.get(stackDepth);
+ out = streamStack.get(stackDepth).asOutputStream();
}
IO_LOG.trace("WRITE ASN.1 START SEQUENCE(type=0x{})", byteToHex(type));
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
index d99f241..4c9a05f 100755
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
@@ -38,6 +38,30 @@
* A mutable sequence of bytes backed by a byte array.
*/
public final class ByteStringBuilder implements ByteSequence {
+ /**
+ * Output stream implementation.
+ */
+ private final class OutputStreamImpl extends OutputStream {
+ @Override
+ public void close() {
+ // Do nothing.
+ }
+
+ @Override
+ public void write(final byte[] bytes) {
+ append(bytes);
+ }
+
+ @Override
+ public void write(final byte[] bytes, final int i, final int i1) {
+ append(bytes, i, i1);
+ }
+
+ @Override
+ public void write(final int i) {
+ append(((byte) (i & 0xFF)));
+ }
+ }
/**
* A sub-sequence of the parent byte string builder. The sub-sequence will
@@ -655,6 +679,20 @@
}
/**
+ * Returns an {@link OutputStream} whose write operations append data to
+ * this byte string builder. The returned output stream will never throw an
+ * {@link IOException} and its {@link OutputStream#close() close} method
+ * does not do anything.
+ *
+ * @return An {@link OutputStream} whose write operations append data to
+ * this byte string builder.
+ */
+ public OutputStream asOutputStream() {
+ // Is it worth caching this?
+ return new OutputStreamImpl();
+ }
+
+ /**
* Returns a {@link ByteSequenceReader} which can be used to incrementally
* read and decode data from this byte string builder.
* <p>
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java
index 3f66d61..bb30eeb 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java
@@ -29,8 +29,11 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterOutputStream;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
@@ -151,6 +154,34 @@
Assert.assertEquals(bsb.getBackingArray().length, 8);
}
+ @Test
+ public void testAsOutputStream() throws Exception {
+ final ByteStringBuilder bsb = new ByteStringBuilder();
+ final OutputStream os = bsb.asOutputStream();
+ os.write((byte) 0x01);
+ os.write(2);
+ os.write(new byte[] { 2, 3, 4, 5 }, 1, 2);
+ os.close();
+ Assert.assertEquals(bsb.length(), 4);
+ Assert.assertEquals(bsb.toByteArray(), new byte[] { 1, 2, 3, 4 });
+ }
+
+ @Test
+ public void testAsOutputStreamCompress() throws Exception {
+ final ByteString data = ByteString.wrap(new byte[4000]);
+ final ByteStringBuilder compressedData = new ByteStringBuilder();
+ final OutputStream compressor = new DeflaterOutputStream(compressedData.asOutputStream());
+ data.copyTo(compressor);
+ compressor.close();
+ Assert.assertTrue(compressedData.length() > 0 && compressedData.length() < 4000);
+
+ final ByteStringBuilder decompressedData = new ByteStringBuilder();
+ final OutputStream decompressor = new InflaterOutputStream(decompressedData.asOutputStream());
+ compressedData.copyTo(decompressor);
+ decompressor.close();
+ Assert.assertEquals(decompressedData.toByteString(), data);
+ }
+
@DataProvider(name = "builderProvider")
private Object[][] byteStringBuilderProvider() throws Exception {
final ByteBuffer testBuffer = ByteBuffer.wrap(EIGHT_BYTES);
--
Gitblit v1.10.0