From fdd9be22de1808af9159a95ae6dd64e6573f5310 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 29 Mar 2013 14:49:41 +0000
Subject: [PATCH] Very minor code cleanup to LDIF package:

---
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java     |  242 ++++++++++----------
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java |   50 +++
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java     |   55 +---
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java        |   37 +++
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java |  139 +++++++----
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java        |   28 ++
 opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java     |  152 ++++-------
 7 files changed, 389 insertions(+), 314 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
index b455c06..fe50021 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
@@ -22,18 +22,31 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2013 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
 
 import static com.forgerock.opendj.util.StaticUtils.toLowerCase;
-import static org.forgerock.opendj.ldap.CoreMessages.*;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_COULD_NOT_BASE64_DECODE_ATTR;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_COULD_NOT_BASE64_DECODE_DN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_INVALID_DN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_INVALID_LEADING_SPACE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_INVALID_URL;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_ATTRIBUTE_NAME;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MULTI_VALUED_SINGLE_VALUED_ATTRIBUTE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_NO_ATTR_NAME;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_NO_DN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_UNEXPECTED_BINARY_OPTION;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_UNKNOWN_ATTRIBUTE_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_URL_IO_ERROR;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_LDIF_DUPLICATE_ATTRIBUTE_VALUE;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.URL;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -63,7 +76,6 @@
 abstract class AbstractLDIFReader extends AbstractLDIFStream {
     static final class KeyValuePair {
         String key;
-
         String value;
     }
 
@@ -94,9 +106,7 @@
 
     static final class LDIFRecord {
         final Iterator<String> iterator;
-
         final LinkedList<String> ldifLines;
-
         final long lineNumber;
 
         private LDIFRecord(final long lineNumber, final LinkedList<String> ldifLines) {
@@ -110,22 +120,15 @@
      * LDIF output stream writer implementation.
      */
     private static final class LDIFReaderInputStreamImpl implements LDIFReaderImpl {
-
         private BufferedReader reader;
 
-        /**
-         * Creates a new LDIF input stream reader implementation.
-         *
-         * @param in
-         *            The input stream to use.
-         */
-        LDIFReaderInputStreamImpl(final InputStream in) {
-            this.reader = new BufferedReader(new InputStreamReader(in));
+        LDIFReaderInputStreamImpl(final Reader reader) {
+            this.reader =
+                    reader instanceof BufferedReader ? (BufferedReader) reader
+                            : new BufferedReader(reader);
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void close() throws IOException {
             if (reader != null) {
                 reader.close();
@@ -133,9 +136,7 @@
             }
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public String readLine() throws IOException {
             String line = null;
             if (reader != null) {
@@ -153,29 +154,18 @@
      * LDIF output stream writer implementation.
      */
     private static final class LDIFReaderListImpl implements LDIFReaderImpl {
-
         private final Iterator<String> iterator;
 
-        /**
-         * Creates a new LDIF list reader.
-         *
-         * @param ldifLines
-         *            The string list.
-         */
         LDIFReaderListImpl(final List<String> ldifLines) {
             this.iterator = ldifLines.iterator();
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void close() throws IOException {
             // Nothing to do.
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public String readLine() throws IOException {
             if (iterator.hasNext()) {
                 return iterator.next();
@@ -186,43 +176,50 @@
     }
 
     RejectedLDIFListener rejectedRecordListener = RejectedLDIFListener.FAIL_FAST;
-
     Schema schema = Schema.getDefaultSchema().asNonStrictSchema();
-
     SchemaValidationPolicy schemaValidationPolicy = SchemaValidationPolicy.ignoreAll();
-
     private final LDIFReaderImpl impl;
-
     private long lineNumber = 0;
 
-    /**
-     * Creates a new LDIF entry reader whose source is the provided input
-     * stream.
-     *
-     * @param in
-     *            The input stream to use.
-     */
     AbstractLDIFReader(final InputStream in) {
-        Validator.ensureNotNull(in);
-        this.impl = new LDIFReaderInputStreamImpl(in);
+        this(new InputStreamReader(in));
     }
 
-    /**
-     * Creates a new LDIF entry reader which will read lines of LDIF from the
-     * provided list.
-     *
-     * @param ldifLines
-     *            The list from which lines of LDIF should be read.
-     */
     AbstractLDIFReader(final List<String> ldifLines) {
         Validator.ensureNotNull(ldifLines);
         this.impl = new LDIFReaderListImpl(ldifLines);
     }
 
+    AbstractLDIFReader(final Reader reader) {
+        this.impl = new LDIFReaderInputStreamImpl(reader);
+    }
+
     final void close0() throws IOException {
         impl.close();
     }
 
+    final void handleMalformedRecord(final LDIFRecord record, final LocalizableMessage message)
+            throws DecodeException {
+        rejectedRecordListener.handleMalformedRecord(record.lineNumber, record.ldifLines, message);
+    }
+
+    final void handleSchemaValidationFailure(final LDIFRecord record,
+            final List<LocalizableMessage> messages) throws DecodeException {
+        rejectedRecordListener.handleSchemaValidationFailure(record.lineNumber, record.ldifLines,
+                messages);
+    }
+
+    final void handleSchemaValidationWarning(final LDIFRecord record,
+            final List<LocalizableMessage> messages) throws DecodeException {
+        rejectedRecordListener.handleSchemaValidationWarning(record.lineNumber, record.ldifLines,
+                messages);
+    }
+
+    final void handleSkippedRecord(final LDIFRecord record, final LocalizableMessage message)
+            throws DecodeException {
+        rejectedRecordListener.handleSkippedRecord(record.lineNumber, record.ldifLines, message);
+    }
+
     final int parseColonPosition(final LDIFRecord record, final String ldifLine)
             throws DecodeException {
         final int colonPos = ldifLine.indexOf(":");
@@ -237,11 +234,12 @@
     final ByteString parseSingleValue(final LDIFRecord record, final String ldifLine,
             final DN entryDN, final int colonPos, final String attrName) throws DecodeException {
 
-        // Look at the character immediately after the colon. If there is
-        // none, then assume an attribute with an empty value. If it is
-        // another colon, then the value must be base64-encoded. If it is a
-        // less-than sign, then assume that it is a URL. Otherwise, it is a
-        // regular value.
+        /*
+         * Look at the character immediately after the colon. If there is none,
+         * then assume an attribute with an empty value. If it is another colon,
+         * then the value must be base64-encoded. If it is a less-than sign,
+         * then assume that it is a URL. Otherwise, it is a regular value.
+         */
         final int length = ldifLine.length();
         ByteString value;
         if (colonPos == length - 1) {
@@ -249,8 +247,10 @@
         } else {
             final char c = ldifLine.charAt(colonPos + 1);
             if (c == ':') {
-                // The value is base64-encoded. Find the first non-blank
-                // character, take the rest of the line, and base64-decode it.
+                /*
+                 * The value is base64-encoded. Find the first non-blank
+                 * character, take the rest of the line, and base64-decode it.
+                 */
                 int pos = colonPos + 2;
                 while (pos < length && ldifLine.charAt(pos) == ' ') {
                     pos++;
@@ -259,15 +259,19 @@
                 try {
                     value = ByteString.valueOfBase64(ldifLine.substring(pos));
                 } catch (final LocalizedIllegalArgumentException e) {
-                    // The value did not have a valid base64-encoding.
+                    /*
+                     * The value did not have a valid base64-encoding.
+                     */
                     final LocalizableMessage message =
                             ERR_LDIF_COULD_NOT_BASE64_DECODE_ATTR.get(entryDN.toString(),
                                     record.lineNumber, ldifLine, e.getMessageObject());
                     throw DecodeException.error(message);
                 }
             } else if (c == '<') {
-                // Find the first non-blank character, decode the rest of the
-                // line as a URL, and read its contents.
+                /*
+                 * Find the first non-blank character, decode the rest of the
+                 * line as a URL, and read its contents.
+                 */
                 int pos = colonPos + 2;
                 while (pos < length && ldifLine.charAt(pos) == ' ') {
                     pos++;
@@ -298,8 +302,10 @@
 
                     value = builder.toByteString();
                 } catch (final Exception e) {
-                    // We were unable to read the contents of that URL for some
-                    // reason.
+                    /*
+                     * We were unable to read the contents of that URL for some
+                     * reason.
+                     */
                     final LocalizableMessage message =
                             ERR_LDIF_URL_IO_ERROR.get(entryDN.toString(), record.lineNumber,
                                     attrName, String.valueOf(contentURL), String.valueOf(e));
@@ -314,8 +320,10 @@
                     }
                 }
             } else {
-                // The rest of the line should be the value. Skip over any
-                // spaces and take the rest of the line as the value.
+                /*
+                 * The rest of the line should be the value. Skip over any
+                 * spaces and take the rest of the line as the value.
+                 */
                 int pos = colonPos + 1;
                 while (pos < length && ldifLine.charAt(pos) == ' ') {
                     pos++;
@@ -332,13 +340,11 @@
         final StringBuilder lastLineBuilder = new StringBuilder();
         final LinkedList<String> ldifLines = new LinkedList<String>();
         long recordLineNumber = 0;
-
         final int stateStart = 0;
         final int stateStartCommentLine = 1;
         final int stateGotLDIFLine = 2;
         final int stateGotCommentLine = 3;
         final int appendingLDIFLine = 4;
-
         int state = stateStart;
 
         while (true) {
@@ -355,8 +361,10 @@
                     // This is a comment at the start of the LDIF record.
                     state = stateStartCommentLine;
                 } else if (isContinuationLine(line)) {
-                    // Fatal: got a continuation line at the start of the
-                    // record.
+                    /*
+                     * Fatal: got a continuation line at the start of the
+                     * record.
+                     */
                     final LocalizableMessage message =
                             ERR_LDIF_INVALID_LEADING_SPACE.get(lineNumber, line);
                     throw DecodeException.fatalError(message);
@@ -473,9 +481,10 @@
                 schemaErrors.add(message);
                 return true;
             default: // Ignore
-                // This should not happen: we should be using a non-strict
-                // schema for
-                // this policy.
+                /*
+                 * This should not happen: we should be using a non-strict
+                 * schema for this policy.
+                 */
                 throw new IllegalStateException("Schema is not consistent with policy", e);
             }
         } catch (final LocalizedIllegalArgumentException e) {
@@ -489,9 +498,11 @@
         final ByteString value =
                 parseSingleValue(record, ldifLine, entry.getName(), colonPos, attrDescr);
 
-        // Skip the attribute if requested before performing any schema
-        // checking: the attribute may have been excluded because it is
-        // known to violate the schema.
+        /*
+         * Skip the attribute if requested before performing any schema
+         * checking: the attribute may have been excluded because it is known to
+         * violate the schema.
+         */
         if (isAttributeExcluded(attributeDescription)) {
             return true;
         }
@@ -515,7 +526,7 @@
         final boolean checkAttributeValues =
                 schemaValidationPolicy.checkAttributeValues().needsChecking();
         if (checkAttributeValues) {
-            LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
+            final LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
             if (!syntax.valueIsAcceptable(value, builder)) {
                 schemaErrors.add(builder.toMessage());
                 if (schemaValidationPolicy.checkAttributeValues().isReject()) {
@@ -586,10 +597,11 @@
             throw DecodeException.error(message);
         }
 
-        // Look at the character immediately after the colon. If there is
-        // none, then assume the null DN. If it is another colon, then the
-        // DN must be base64-encoded. Otherwise, it may be one or more
-        // spaces.
+        /*
+         * Look at the character immediately after the colon. If there is none,
+         * then assume the null DN. If it is another colon, then the DN must be
+         * base64-encoded. Otherwise, it may be one or more spaces.
+         */
         final int length = ldifLine.length();
         if (colonPos == length - 1) {
             return DN.rootDN();
@@ -598,8 +610,10 @@
         String dnString = null;
 
         if (ldifLine.charAt(colonPos + 1) == ':') {
-            // The DN is base64-encoded. Find the first non-blank character
-            // and take the rest of the line and base64-decode it.
+            /*
+             * The DN is base64-encoded. Find the first non-blank character and
+             * take the rest of the line and base64-decode it.
+             */
             int pos = colonPos + 2;
             while (pos < length && ldifLine.charAt(pos) == ' ') {
                 pos++;
@@ -616,8 +630,10 @@
                 throw DecodeException.error(message);
             }
         } else {
-            // The rest of the value should be the DN. Skip over any spaces
-            // and attempt to decode the rest of the line as the DN.
+            /*
+             * The rest of the value should be the DN. Skip over any spaces and
+             * attempt to decode the rest of the line as the DN.
+             */
             int pos = colonPos + 1;
             while (pos < length && ldifLine.charAt(pos) == ' ') {
                 pos++;
@@ -645,8 +661,10 @@
         }
         pair.key = ldifLine.substring(0, colonPos);
 
-        // Look at the character immediately after the colon. If there is
-        // none, then no value was specified. Throw an exception
+        /*
+         * Look at the character immediately after the colon. If there is none,
+         * then no value was specified. Throw an exception
+         */
         final int length = ldifLine.length();
         if (colonPos == length - 1) {
             pair.key = null;
@@ -654,8 +672,10 @@
         }
 
         if (allowBase64 && ldifLine.charAt(colonPos + 1) == ':') {
-            // The value is base64-encoded. Find the first non-blank
-            // character, take the rest of the line, and base64-decode it.
+            /*
+             * The value is base64-encoded. Find the first non-blank character,
+             * take the rest of the line, and base64-decode it.
+             */
             int pos = colonPos + 2;
             while (pos < length && ldifLine.charAt(pos) == ' ') {
                 pos++;
@@ -668,9 +688,11 @@
                 return ldifLine;
             }
         } else {
-            // The rest of the value should be the changetype. Skip over any
-            // spaces and attempt to decode the rest of the line as the
-            // changetype string.
+            /*
+             * The rest of the value should be the changetype. Skip over any
+             * spaces and attempt to decode the rest of the line as the
+             * changetype string.
+             */
             int pos = colonPos + 1;
             while (pos < length && ldifLine.charAt(pos) == ' ') {
                 pos++;
@@ -682,33 +704,12 @@
         return ldifLine;
     }
 
-    final void handleMalformedRecord(final LDIFRecord record, final LocalizableMessage message)
-            throws DecodeException {
-        rejectedRecordListener.handleMalformedRecord(record.lineNumber, record.ldifLines, message);
-    }
-
-    final void handleSchemaValidationFailure(final LDIFRecord record,
-            final List<LocalizableMessage> messages) throws DecodeException {
-        rejectedRecordListener.handleSchemaValidationFailure(record.lineNumber, record.ldifLines,
-                messages);
-    }
-
-    final void handleSchemaValidationWarning(final LDIFRecord record,
-            final List<LocalizableMessage> messages) throws DecodeException {
-        rejectedRecordListener.handleSchemaValidationWarning(record.lineNumber, record.ldifLines,
-                messages);
-    }
-
-    final void handleSkippedRecord(final LDIFRecord record, final LocalizableMessage message)
-            throws DecodeException {
-        rejectedRecordListener.handleSkippedRecord(record.lineNumber, record.ldifLines, message);
-    }
-
-    // Determine whether the provided line is a continuation line. Note
-    // that while RFC 2849 technically only allows a space in this
-    // position, both OpenLDAP and the Sun Java System Directory Server
-    // allow a tab as well, so we will too for compatibility reasons. See
-    // issue #852 for details.
+    /*
+     * Determine whether the provided line is a continuation line. Note that
+     * while RFC 2849 technically only allows a space in this position, both
+     * OpenLDAP and the Sun Java System Directory Server allow a tab as well, so
+     * we will too for compatibility reasons. See issue #852 for details.
+     */
     private boolean isContinuationLine(final String line) {
         return line.charAt(0) == ' ' || line.charAt(0) == '\t';
     }
@@ -720,5 +721,4 @@
         }
         return line;
     }
-
 }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java
index 15498a7..44a063b 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2011 ForgeRock AS
+ *      Portions copyright 2011-2013 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
@@ -42,51 +42,30 @@
  * Common LDIF reader/writer functionality.
  */
 abstract class AbstractLDIFStream {
-
     final Set<AttributeDescription> excludeAttributes = new HashSet<AttributeDescription>();
-
-    boolean excludeOperationalAttributes = false;
-
-    boolean excludeUserAttributes = false;
-
-    final Set<AttributeDescription> includeAttributes = new HashSet<AttributeDescription>();
-
-    final Set<DN> includeBranches = new HashSet<DN>();
-
     final Set<DN> excludeBranches = new HashSet<DN>();
-
+    final List<Matcher> excludeFilters = new LinkedList<Matcher>();
+    boolean excludeOperationalAttributes = false;
+    boolean excludeUserAttributes = false;
+    final Set<AttributeDescription> includeAttributes = new HashSet<AttributeDescription>();
+    final Set<DN> includeBranches = new HashSet<DN>();
     final List<Matcher> includeFilters = new LinkedList<Matcher>();
 
-    final List<Matcher> excludeFilters = new LinkedList<Matcher>();
-
-    /**
-     * Creates a new abstract LDIF stream.
-     */
     AbstractLDIFStream() {
         // Nothing to do.
     }
 
     final boolean isAttributeExcluded(final AttributeDescription attributeDescription) {
+        // Let explicit include override more general exclude.
         if (!excludeAttributes.isEmpty() && excludeAttributes.contains(attributeDescription)) {
             return true;
-        }
-
-        // Let explicit include override more general exclude.
-        if (!includeAttributes.isEmpty()) {
+        } else if (!includeAttributes.isEmpty()) {
             return !includeAttributes.contains(attributeDescription);
+        } else {
+            final AttributeType type = attributeDescription.getAttributeType();
+            return (excludeOperationalAttributes && type.isOperational())
+                    || (excludeUserAttributes && !type.isOperational());
         }
-
-        final AttributeType type = attributeDescription.getAttributeType();
-
-        if (excludeOperationalAttributes && type.isOperational()) {
-            return true;
-        }
-
-        if (excludeUserAttributes && !type.isOperational()) {
-            return true;
-        }
-
-        return false;
     }
 
     final boolean isBranchExcluded(final DN dn) {
@@ -97,7 +76,6 @@
                 }
             }
         }
-
         if (!includeBranches.isEmpty()) {
             for (final DN includeBranch : includeBranches) {
                 if (includeBranch.isSuperiorOrEqualTo(dn)) {
@@ -105,9 +83,9 @@
                 }
             }
             return true;
+        } else {
+            return false;
         }
-
-        return false;
     }
 
     final boolean isEntryExcluded(final Entry entry) {
@@ -118,7 +96,6 @@
                 }
             }
         }
-
         if (!includeFilters.isEmpty()) {
             for (final Matcher includeFilter : includeFilters) {
                 if (includeFilter.matches(entry).toBoolean()) {
@@ -126,9 +103,9 @@
                 }
             }
             return true;
+        } else {
+            return false;
         }
-
-        return false;
     }
 
 }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
index f9e4937..f2469a8 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2011-2012 ForgeRock AS
+ *      Portions copyright 2011-2013 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
@@ -31,6 +31,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.util.List;
 import java.util.regex.Pattern;
 
@@ -100,45 +101,29 @@
      * LDIF string list writer implementation.
      */
     private static final class LDIFWriterListImpl implements LDIFWriterImpl {
-
         private final StringBuilder builder = new StringBuilder();
-
         private final List<String> ldifLines;
 
-        /**
-         * Creates a new LDIF list writer.
-         *
-         * @param ldifLines
-         *            The string list.
-         */
         LDIFWriterListImpl(final List<String> ldifLines) {
             this.ldifLines = ldifLines;
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void close() throws IOException {
             // Nothing to do.
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void flush() throws IOException {
             // Nothing to do.
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void print(final CharSequence s) throws IOException {
             builder.append(s);
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void println() throws IOException {
             ldifLines.add(builder.toString());
             builder.setLength(0);
@@ -149,81 +134,54 @@
      * LDIF output stream writer implementation.
      */
     private static final class LDIFWriterOutputStreamImpl implements LDIFWriterImpl {
-
         private final BufferedWriter writer;
 
-        /**
-         * Creates a new LDIF output stream writer.
-         *
-         * @param out
-         *            The output stream.
-         */
-        LDIFWriterOutputStreamImpl(final OutputStream out) {
-            this.writer = new BufferedWriter(new OutputStreamWriter(out));
+        LDIFWriterOutputStreamImpl(final Writer writer) {
+            this.writer =
+                    writer instanceof BufferedWriter ? (BufferedWriter) writer
+                            : new BufferedWriter(writer);
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void close() throws IOException {
             writer.close();
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void flush() throws IOException {
             writer.flush();
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void print(final CharSequence s) throws IOException {
             writer.append(s);
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        @Override
         public void println() throws IOException {
             writer.newLine();
         }
     }
 
-    // Regular expression used for splitting comments on line-breaks.
+    /*
+     * Regular expression used for splitting comments on line-breaks.
+     */
     private static final Pattern SPLIT_NEWLINE = Pattern.compile("\\r?\\n");
-
     boolean addUserFriendlyComments = false;
-
     final LDIFWriterImpl impl;
-
     int wrapColumn = 0;
-
     private final StringBuilder builder = new StringBuilder(80);
 
-    /**
-     * Creates a new LDIF entry writer which will append lines of LDIF to the
-     * provided list.
-     *
-     * @param ldifLines
-     *            The list to which lines of LDIF should be appended.
-     */
-    public AbstractLDIFWriter(final List<String> ldifLines) {
-        Validator.ensureNotNull(ldifLines);
+    AbstractLDIFWriter(final List<String> ldifLines) {
         this.impl = new LDIFWriterListImpl(ldifLines);
     }
 
-    /**
-     * Creates a new LDIF entry writer whose destination is the provided output
-     * stream.
-     *
-     * @param out
-     *            The output stream to use.
-     */
-    public AbstractLDIFWriter(final OutputStream out) {
-        Validator.ensureNotNull(out);
-        this.impl = new LDIFWriterOutputStreamImpl(out);
+    AbstractLDIFWriter(final OutputStream out) {
+        this(new OutputStreamWriter(out));
+    }
+
+    AbstractLDIFWriter(final Writer writer) {
+        this.impl = new LDIFWriterOutputStreamImpl(writer);
     }
 
     final void close0() throws IOException {
@@ -238,12 +196,16 @@
     final void writeComment0(final CharSequence comment) throws IOException {
         Validator.ensureNotNull(comment);
 
-        // First, break up the comment into multiple lines to preserve the
-        // original spacing that it contained.
+        /*
+         * First, break up the comment into multiple lines to preserve the
+         * original spacing that it contained.
+         */
         final String[] lines = SPLIT_NEWLINE.split(comment);
 
-        // Now iterate through the lines and write them out, prefixing and
-        // wrapping them as necessary.
+        /*
+         * Now iterate through the lines and write them out, prefixing and
+         * wrapping them as necessary.
+         */
         for (final String line : lines) {
             if (!shouldWrap()) {
                 impl.print("# ");
@@ -251,7 +213,6 @@
                 impl.println();
             } else {
                 final int breakColumn = wrapColumn - 2;
-
                 if (line.length() <= breakColumn) {
                     impl.print("# ");
                     impl.print(line);
@@ -267,7 +228,6 @@
                             startPos = line.length();
                         } else {
                             final int endPos = startPos + breakColumn;
-
                             int i = endPos - 1;
                             while (i > startPos) {
                                 if (line.charAt(i) == ' ') {
@@ -278,19 +238,17 @@
                                     startPos = i + 1;
                                     continue outerLoop;
                                 }
-
                                 i--;
                             }
 
-                            // If we've gotten here, then there are no spaces on
-                            // the
-                            // entire line. If that happens, then we'll have to
-                            // break
-                            // in the middle of a word.
+                            /*
+                             * If we've gotten here, then there are no spaces on
+                             * the entire line. If that happens, then we'll have
+                             * to break in the middle of a word.
+                             */
                             impl.print("# ");
                             impl.print(line.substring(startPos, endPos));
                             impl.println();
-
                             startPos = endPos;
                         }
                     }
@@ -304,7 +262,6 @@
             final StringBuilder key = new StringBuilder("control: ");
             key.append(control.getOID());
             key.append(control.isCritical() ? " true" : " false");
-
             if (control.hasValue()) {
                 writeKeyAndValue(key, control.getValue());
             } else {
@@ -317,17 +274,20 @@
             throws IOException {
         builder.setLength(0);
 
-        // If the value is empty, then just append a single colon and a
-        // single space.
+        /*
+         * If the value is empty, then just append a single colon and a single
+         * space.
+         */
         if (value.length() == 0) {
             builder.append(key);
             builder.append(": ");
         } else if (needsBase64Encoding(value)) {
             if (addUserFriendlyComments) {
-                // TODO: Only display comments for valid UTF-8 values, not
-                // binary values.
+                /*
+                 * TODO: Only display comments for valid UTF-8 values, not
+                 * binary values.
+                 */
             }
-
             builder.setLength(0);
             builder.append(key);
             builder.append(":: ");
@@ -337,7 +297,6 @@
             builder.append(": ");
             builder.append(value.toString());
         }
-
         writeLine(builder);
     }
 
@@ -372,8 +331,10 @@
             return false;
         }
 
-        // If the value starts with a space, colon, or less than, then it
-        // needs to be base64 encoded.
+        /*
+         * If the value starts with a space, colon, or less than, then it needs
+         * to be base64 encoded.
+         */
         switch (bytes.byteAt(0)) {
         case 0x20: // Space
         case 0x3A: // Colon
@@ -381,14 +342,17 @@
             return true;
         }
 
-        // If the value ends with a space, then it needs to be
-        // base64 encoded.
+        /*
+         * If the value ends with a space, then it needs to be base64 encoded.
+         */
         if (length > 1 && bytes.byteAt(length - 1) == 0x20) {
             return true;
         }
 
-        // If the value contains a null, newline, or return character, then
-        // it needs to be base64 encoded.
+        /*
+         * If the value contains a null, newline, or return character, then it
+         * needs to be base64 encoded.
+         */
         byte b;
         for (int i = 0; i < bytes.length(); i++) {
             b = bytes.byteAt(i);
@@ -404,7 +368,7 @@
             }
         }
 
-        // If we've made it here, then there's no reason to base64 encode.
+        /* If we've made it here, then there's no reason to base64 encode. */
         return false;
     }
 
@@ -415,11 +379,9 @@
     @SuppressWarnings("unused")
     private void writeKeyAndURL(final CharSequence key, final CharSequence url) throws IOException {
         builder.setLength(0);
-
         builder.append(key);
         builder.append(":: ");
         builder.append(url);
-
         writeLine(builder);
     }
 }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
index d9bd11d..15ad979 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
@@ -28,10 +28,30 @@
 package org.forgerock.opendj.ldif;
 
 import static com.forgerock.opendj.util.StaticUtils.toLowerCase;
-import static org.forgerock.opendj.ldap.CoreMessages.*;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_ATTRIBUTE_NAME_MISMATCH;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_BAD_CHANGE_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_BAD_MODIFICATION_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_CHANGE_EXCLUDED_BY_DN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_ATTRIBUTE_NAME;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_CHANGE_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_CONTROL;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_DELETE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_DELETE_OLD_RDN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_MODIFICATION_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_NEW_RDN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_MALFORMED_NEW_SUPERIOR;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_NO_CHANGE_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_NO_DELETE_OLD_RDN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_NO_NEW_RDN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_UNEXPECTED_BINARY_OPTION;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_UNKNOWN_ATTRIBUTE_TYPE;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
@@ -91,6 +111,12 @@
  *      Interchange Format (LDIF) - Technical Specification </a>
  */
 public final class LDIFChangeRecordReader extends AbstractLDIFReader implements ChangeRecordReader {
+    private static final Pattern CONTROL_REGEX = Pattern
+            .compile("^\\s*(\\d+(.\\d+)*)(\\s+((true)|(false)))?\\s*(:(:)?\\s*?\\S+)?\\s*$");
+
+    // Poison used to indicate end of LDIF.
+    private static final ChangeRecord EOF = Requests.newAddRequest(DN.rootDN());
+
     /**
      * Parses the provided array of LDIF lines as a single LDIF change record.
      *
@@ -140,12 +166,6 @@
 
     private ChangeRecord nextChangeRecord = null;
 
-    // Poison used to indicate end of LDIF.
-    private static final ChangeRecord EOF = Requests.newAddRequest(DN.rootDN());
-
-    private static final Pattern CONTROL_REGEX =
-            Pattern.compile("^\\s*(\\d+(.\\d+)*)(\\s+((true)|(false)))?\\s*(:(:)?\\s*?\\S+)?\\s*$");
-
     /**
      * Creates a new LDIF change record reader whose source is the provided
      * input stream.
@@ -173,6 +193,19 @@
     }
 
     /**
+     * Creates a new LDIF change record reader whose source is the provided
+     * character stream reader.
+     *
+     * @param reader
+     *            The character stream reader to use.
+     * @throws NullPointerException
+     *             If {@code reader} was {@code null}.
+     */
+    public LDIFChangeRecordReader(final Reader reader) {
+        super(reader);
+    }
+
+    /**
      * Creates a new LDIF change record reader which will read lines of LDIF
      * from the provided array of LDIF lines.
      *
@@ -379,8 +412,10 @@
             }
 
             try {
-                // Read the DN of the entry and see if it is one that should be
-                // included in the import.
+                /*
+                 * Read the DN of the entry and see if it is one that should be
+                 * included in the import.
+                 */
                 final DN entryDN = readLDIFRecordDN(record);
                 if (entryDN == null) {
                     // Skip version record.
@@ -450,7 +485,7 @@
 
                     // Add the controls to the record.
                     if (controls != null) {
-                        for (Control control : controls) {
+                        for (final Control control : controls) {
                             nextChangeRecord.addControl(control);
                         }
                     }
@@ -463,27 +498,6 @@
         return nextChangeRecord;
     }
 
-    private Control parseControl(DN entryDN, LDIFRecord record, String ldifLine, String value)
-            throws DecodeException {
-
-        Matcher matcher = CONTROL_REGEX.matcher(value);
-        if (!matcher.matches()) {
-            final LocalizableMessage message =
-                    ERR_LDIF_MALFORMED_CONTROL.get(record.lineNumber, entryDN.toString(), ldifLine);
-            throw DecodeException.error(message);
-        }
-
-        String oid = matcher.group(1);
-        boolean isCritical = matcher.group(5) != null;
-        String controlValueString = matcher.group(7);
-        ByteString controlValue = null;
-        if (controlValueString != null) {
-            controlValue = parseSingleValue(record, ldifLine, entryDN,  ldifLine.indexOf(':', 8), oid);
-        }
-
-        return GenericControl.newControl(oid, isCritical, controlValue);
-    }
-
     private ChangeRecord parseAddChangeRecordEntry(final DN entryDN, final String lastLDIFLine,
             final LDIFRecord record) throws DecodeException {
         // Use an Entry for the AttributeSequence.
@@ -520,6 +534,25 @@
         return Requests.newAddRequest(entry);
     }
 
+    private Control parseControl(final DN entryDN, final LDIFRecord record, final String ldifLine,
+            final String value) throws DecodeException {
+        final Matcher matcher = CONTROL_REGEX.matcher(value);
+        if (!matcher.matches()) {
+            final LocalizableMessage message =
+                    ERR_LDIF_MALFORMED_CONTROL.get(record.lineNumber, entryDN.toString(), ldifLine);
+            throw DecodeException.error(message);
+        }
+        final String oid = matcher.group(1);
+        final boolean isCritical = matcher.group(5) != null;
+        final String controlValueString = matcher.group(7);
+        ByteString controlValue = null;
+        if (controlValueString != null) {
+            controlValue =
+                    parseSingleValue(record, ldifLine, entryDN, ldifLine.indexOf(':', 8), oid);
+        }
+        return GenericControl.newControl(oid, isCritical, controlValue);
+    }
+
     private ChangeRecord parseDeleteChangeRecordEntry(final DN entryDN, final LDIFRecord record)
             throws DecodeException {
         if (record.iterator.hasNext()) {
@@ -582,9 +615,10 @@
                     schemaErrors.add(message);
                     continue;
                 default: // Ignore
-                    // This should not happen: we should be using a non-strict
-                    // schema for
-                    // this policy.
+                    /*
+                     * This should not happen: we should be using a non-strict
+                     * schema for this policy.
+                     */
                     throw new IllegalStateException("Schema is not consistent with policy", e);
                 }
             } catch (final LocalizedIllegalArgumentException e) {
@@ -594,9 +628,11 @@
                 throw DecodeException.error(message);
             }
 
-            // Skip the attribute if requested before performing any schema
-            // checking: the attribute may have been excluded because it is
-            // known to violate the schema.
+            /*
+             * Skip the attribute if requested before performing any schema
+             * checking: the attribute may have been excluded because it is
+             * known to violate the schema.
+             */
             if (isAttributeExcluded(attributeDescription)) {
                 continue;
             }
@@ -620,8 +656,10 @@
                 attributeDescription = attributeDescription.withOption("binary");
             }
 
-            // Now go through the rest of the attributes until the "-" line is
-            // reached.
+            /*
+             * Now go through the rest of the attributes until the "-" line is
+             * reached.
+             */
             attributeValues.clear();
             while (record.iterator.hasNext()) {
                 ldifLine = record.iterator.next();
@@ -637,9 +675,11 @@
                 try {
                     attributeDescription2 = AttributeDescription.valueOf(attrDescr, schema);
                 } catch (final LocalizedIllegalArgumentException e) {
-                    // No need to catch schema exception here because it implies
-                    // that the
-                    // attribute name is wrong and the record is malformed.
+                    /*
+                     * No need to catch schema exception here because it implies
+                     * that the attribute name is wrong and the record is
+                     * malformed.
+                     */
                     final LocalizableMessage message =
                             ERR_LDIF_MALFORMED_ATTRIBUTE_NAME.get(record.lineNumber, entryDN
                                     .toString(), attrDescr);
@@ -664,15 +704,14 @@
                 final ByteString value =
                         parseSingleValue(record, ldifLine, entryDN, colonPos, attrDescr);
                 if (schemaValidationPolicy.checkAttributeValues().needsChecking()) {
-                    LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
+                    final LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
                     if (!syntax.valueIsAcceptable(value, builder)) {
-                        // Just log a message, but don't skip the value since
-                        // this could
-                        // change the semantics of the modification (e.g. if all
-                        // values in a
-                        // delete are skipped then this implies that the whole
-                        // attribute
-                        // should be removed).
+                        /*
+                         * Just log a message, but don't skip the value since
+                         * this could change the semantics of the modification
+                         * (e.g. if all values in a delete are skipped then this
+                         * implies that the whole attribute should be removed).
+                         */
                         if (schemaValidationPolicy.checkAttributeValues().isReject()) {
                             schemaValidationFailure = true;
                         }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java
index 15387ac..332fe71 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java
@@ -22,13 +22,15 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
+ *      Portions copyright 2012-2013 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldif;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.util.List;
 
 import org.forgerock.opendj.ldap.Attribute;
@@ -72,6 +74,25 @@
 public final class LDIFChangeRecordWriter extends AbstractLDIFWriter implements ChangeRecordWriter {
 
     /**
+     * Returns the LDIF string representation of the provided change record.
+     *
+     * @param change
+     *            The change record.
+     * @return The LDIF string representation of the provided change record.
+     */
+    public static String toString(final ChangeRecord change) {
+        final StringWriter writer = new StringWriter(128);
+        try {
+            new LDIFChangeRecordWriter(writer).setAddUserFriendlyComments(true).writeChangeRecord(
+                    change).close();
+        } catch (final IOException e) {
+            // Should never happen.
+            throw new IllegalStateException(e);
+        }
+        return writer.toString();
+    }
+
+    /**
      * Creates a new LDIF change record writer which will append lines of LDIF
      * to the provided list.
      *
@@ -94,8 +115,20 @@
     }
 
     /**
+     * Creates a new LDIF change record writer whose destination is the provided
+     * character stream writer.
+     *
+     * @param writer
+     *            The character stream writer to use.
+     */
+    public LDIFChangeRecordWriter(final Writer writer) {
+        super(writer);
+    }
+
+    /**
      * {@inheritDoc}
      */
+    @Override
     public void close() throws IOException {
         close0();
     }
@@ -103,6 +136,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void flush() throws IOException {
         flush0();
     }
@@ -230,6 +264,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeChangeRecord(final AddRequest change) throws IOException {
         Validator.ensureNotNull(change);
 
@@ -262,6 +297,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeChangeRecord(final ChangeRecord change) throws IOException {
         Validator.ensureNotNull(change);
 
@@ -281,6 +317,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeChangeRecord(final DeleteRequest change) throws IOException {
         Validator.ensureNotNull(change);
 
@@ -302,6 +339,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeChangeRecord(final ModifyDNRequest change)
             throws IOException {
         Validator.ensureNotNull(change);
@@ -314,9 +352,11 @@
         writeKeyAndValue("dn", change.getName().toString());
         writeControls(change.getControls());
 
-        // Write the changetype. Some older tools may not support the
-        // "moddn" changetype, so only use it if a newSuperior element has
-        // been provided, but use modrdn elsewhere.
+        /*
+         * Write the changetype. Some older tools may not support the "moddn"
+         * changetype, so only use it if a newSuperior element has been
+         * provided, but use modrdn elsewhere.
+         */
         if (change.getNewSuperior() == null) {
             writeLine("changetype: modrdn");
         } else {
@@ -338,6 +378,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeChangeRecord(final ModifyRequest change) throws IOException {
         Validator.ensureNotNull(change);
 
@@ -381,6 +422,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFChangeRecordWriter writeComment(final CharSequence comment) throws IOException {
         writeComment0(comment);
         return this;
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
index 1be1abb..878a3e8 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
@@ -22,15 +22,20 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011-2012 ForgeRock AS
+ *      Portions copyright 2011-2013 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
 
-import static org.forgerock.opendj.ldap.CoreMessages.*;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_ENTRY_EXCLUDED_BY_DN;
+import static org.forgerock.opendj.ldap.CoreMessages.ERR_LDIF_ENTRY_EXCLUDED_BY_FILTER;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND;
+import static org.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -134,6 +139,19 @@
     }
 
     /**
+     * Creates a new LDIF entry reader whose source is the provided character
+     * stream reader.
+     *
+     * @param reader
+     *            The character stream reader to use.
+     * @throws NullPointerException
+     *             If {@code reader} was {@code null}.
+     */
+    public LDIFEntryReader(final Reader reader) {
+        super(reader);
+    }
+
+    /**
      * Creates a new LDIF entry reader which will read lines of LDIF from the
      * provided array of LDIF lines.
      *
@@ -366,8 +384,10 @@
             }
 
             try {
-                // Read the DN of the entry and see if it is one that should be
-                // included in the import.
+                /*
+                 * Read the DN of the entry and see if it is one that should be
+                 * included in the import.
+                 */
                 final DN entryDN = readLDIFRecordDN(record);
                 if (entryDN == null) {
                     // Skip version record.
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java
index 60d76c8..86bf289 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java
@@ -22,13 +22,15 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
+ *      Portions copyright 2012-2013 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldif;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.util.List;
 
 import org.forgerock.opendj.ldap.Attribute;
@@ -50,6 +52,24 @@
 public final class LDIFEntryWriter extends AbstractLDIFWriter implements EntryWriter {
 
     /**
+     * Returns the LDIF string representation of the provided entry.
+     *
+     * @param entry
+     *            The entry.
+     * @return The LDIF string representation of the provided entry.
+     */
+    public static String toString(final Entry entry) {
+        final StringWriter writer = new StringWriter(128);
+        try {
+            new LDIFEntryWriter(writer).setAddUserFriendlyComments(true).writeEntry(entry).close();
+        } catch (final IOException e) {
+            // Should never happen.
+            throw new IllegalStateException(e);
+        }
+        return writer.toString();
+    }
+
+    /**
      * Creates a new LDIF entry writer which will append lines of LDIF to the
      * provided list.
      *
@@ -72,8 +92,20 @@
     }
 
     /**
+     * Creates a new LDIF entry writer whose destination is the provided
+     * character stream writer.
+     *
+     * @param writer
+     *            The character stream writer to use.
+     */
+    public LDIFEntryWriter(final Writer writer) {
+        super(writer);
+    }
+
+    /**
      * {@inheritDoc}
      */
+    @Override
     public void close() throws IOException {
         close0();
     }
@@ -81,6 +113,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void flush() throws IOException {
         flush0();
     }
@@ -235,6 +268,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFEntryWriter writeComment(final CharSequence comment) throws IOException {
         writeComment0(comment);
         return this;
@@ -243,6 +277,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public LDIFEntryWriter writeEntry(final Entry entry) throws IOException {
         Validator.ensureNotNull(entry);
 

--
Gitblit v1.10.0