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

Nicolas Capponi
02.42.2015 e1e337ccc14b01d5405cef806883e880b0243779
OPENDJ-1585 Re-implement DN normalization in server

* Same behavior than SDK for DN normalization

* Convert all occurences of DN.toNormalizedString() using
** DN.toString()
** DN.toIrreversibleReadableString()
** DN.toIrreversibleNormalizedByteString()

47 files modified
1381 ■■■■ changed files
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/ChangelogBackend.java 10 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/DN2URI.java 78 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java 112 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/RootContainer.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java 49 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/JebFormat.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/AuthenticatedUsers.java 21 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/EntryCacheConfigManager.java 63 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/GroupManager.java 31 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/SubentryManager.java 84 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProvider.java 9 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/EntryUUIDVirtualAttributeProvider.java 21 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProvider.java 15 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/plugins/EntryUUIDPlugin.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java 7 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/EntryHistorical.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 10 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/MultimasterReplication.java 12 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/LightweightServerHandler.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/MessageHandler.java 6 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationDomainMonitor.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationServer.java 13 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationServerDomain.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/file/FileReplicaDB.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDB.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/ReplicationDbEnv.java 35 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/service/ReplicationBroker.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/service/ReplicationDomain.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java 6 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tasks/ImportTask.java 19 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/DBTest.java 20 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/ImportLDIF.java 8 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/DN.java 122 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/RDN.java 188 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestJebFormat.java 42 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/SubentryManagerTestCase.java 6 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryUUIDVirtualAttributeProviderTestCase.java 10 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestBindResponseProtocolOp.java 8 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestDN.java 243 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestRDN.java 56 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/ChangelogBackend.java
@@ -21,7 +21,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2014 ForgeRock AS.
 *      Copyright 2014-2015 ForgeRock AS.
 */
package org.opends.server.backends;
@@ -29,7 +29,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -745,12 +744,7 @@
   */
  private static Set<DN> getExcludedBaseDNs() throws DirectoryException
  {
    final Set<DN> excludedDNs = new HashSet<DN>();
    for (String dn : getExcludedChangelogDomains())
    {
      excludedDNs.add(DN.valueOf(dn));
    }
    return excludedDNs;
    return getExcludedChangelogDomains();
  }
  /**
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/DN2URI.java
@@ -22,19 +22,21 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.io.UnsupportedEncodingException;
import java.util.*;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteSequenceReader;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteStringBuilder;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.util.Pair;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.SearchOperation;
import org.opends.server.types.*;
@@ -51,16 +53,22 @@
/**
 * This class represents the referral database which contains URIs from referral
 * entries.  The key is the DN of the referral entry and the value is that of a
 * labeled URI in the ref attribute for that entry. Duplicate keys are permitted
 * since a referral entry can contain multiple values of the ref attribute.  Key
 * order is the same as in the DN database so that all referrals in a subtree
 * can be retrieved by cursoring through a range of the records.
 * entries.
 * <p>
 * The key is the DN of the referral entry and the value is that of a pair
 * (labeled URI in the ref attribute for that entry, DN). The DN must be
 * duplicated in the value because the key is suitable for comparisons but is
 * not reversible to a valid DN. Duplicate keys are permitted since a referral
 * entry can contain multiple values of the ref attribute. Key order is the same
 * as in the DN database so that all referrals in a subtree can be retrieved by
 * cursoring through a range of the records.
 */
public class DN2URI extends DatabaseContainer
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  private static final byte STRING_SEPARATOR = (byte) 0x00;
  /**
   * The key comparator used for the DN database.
   */
@@ -124,9 +132,8 @@
       throws DatabaseException
  {
    byte[] normDN = JebFormat.dnToDNKey(dn, prefixRDNComponents);
    byte[] URIBytes = StaticUtils.getBytes(labeledURI);
    DatabaseEntry key = new DatabaseEntry(normDN);
    DatabaseEntry data = new DatabaseEntry(URIBytes);
    DatabaseEntry data = new DatabaseEntry(encodeURIAndDN(labeledURI, dn));
    // The JE insert method does not permit duplicate keys so we must use the
    // put method.
@@ -138,6 +145,40 @@
    return false;
  }
  private byte[] encodeURIAndDN(String labeledURI, DN dn)
  {
    return new ByteStringBuilder()
      .append(labeledURI)
      .append(STRING_SEPARATOR)
      .append(dn.toString())
      .toByteArray();
  }
  private Pair<String, DN> decodeURIAndDN(byte[] data) throws DirectoryException {
    try {
      final ByteSequenceReader reader = ByteString.valueOf(data).asReader();
      final String labeledURI = reader.getString(getNextStringLength(reader));
      // skip the string separator
      reader.skip(1);
      final DN dn = DN.valueOf(reader.getString(reader.remaining()));
      return Pair.of(labeledURI, dn);
    }
    catch (Exception e) {
       throw new DirectoryException(ResultCode.OPERATIONS_ERROR, ERR_JEB_DATABASE_EXCEPTION.get(e));
    }
  }
  /** Returns the length of next string by looking for the zero byte used as separator. */
  private int getNextStringLength(ByteSequenceReader reader)
  {
    int length = 0;
    while (reader.peek(length) != STRING_SEPARATOR)
    {
      length++;
    }
    return length;
  }
  /**
   * Delete URI values for a given referral entry from the referral database.
   *
@@ -528,7 +569,8 @@
            Set<String> labeledURIs = new LinkedHashSet<String>(cursor.count());
            do
            {
              String labeledURI = new String(data.getData(), "UTF-8");
              final Pair<String, DN> uriAndDN = decodeURIAndDN(data.getData());
              final String labeledURI = uriAndDN.getFirst();
              labeledURIs.add(labeledURI);
              status = cursor.getNextDup(key, data, DEFAULT);
            } while (status == OperationStatus.SUCCESS);
@@ -546,10 +588,6 @@
    {
      logger.traceException(e);
    }
    catch (UnsupportedEncodingException e)
    {
      logger.traceException(e);
    }
  }
  /**
@@ -584,8 +622,7 @@
     * find subordinates of the base entry from the top of the tree
     * downwards.
     */
    byte[] baseDN = JebFormat.dnToDNKey(searchOp.getBaseDN(),
                                          prefixRDNComponents);
    byte[] baseDN = JebFormat.dnToDNKey(searchOp.getBaseDN(), prefixRDNComponents);
    final byte special = 0x00;
    byte[] suffix = Arrays.copyOf(baseDN, baseDN.length+1);
    suffix[suffix.length - 1] = special;
@@ -622,7 +659,9 @@
          }
          // We have found a subordinate referral.
          DN dn = dnFromDNKey(key.getData(), entryContainer.getBaseDN());
          final Pair<String, DN> uriAndDN = decodeURIAndDN(data.getData());
          final String labeledURI = uriAndDN.getFirst();
          final DN dn = uriAndDN.getSecond();
          // Make sure the referral is within scope.
          if (searchOp.getScope() == SearchScope.SINGLE_LEVEL
@@ -636,7 +675,6 @@
          do
          {
            // Remove the label part of the labeled URI if there is a label.
            String labeledURI = new String(data.getData(), "UTF-8");
            String uri = labeledURI;
            int i = labeledURI.indexOf(' ');
            if (i != -1)
@@ -699,10 +737,6 @@
    {
      logger.traceException(e);
    }
    catch (UnsupportedEncodingException e)
    {
      logger.traceException(e);
    }
    return true;
  }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 *      Portions copyright 2013 Manuel Gaupp
 */
package org.opends.server.backends.jeb;
@@ -1675,8 +1675,7 @@
            if (!pluginResult.continueProcessing())
            {
              LocalizableMessage message =
                      ERR_JEB_DELETE_ABORTED_BY_SUBORDINATE_PLUGIN.get(
                      dnFromDNKey(key.getData(), getBaseDN()));
                  ERR_JEB_DELETE_ABORTED_BY_SUBORDINATE_PLUGIN.get(subordinateEntry.getName().toString());
              throw new DirectoryException(
                  DirectoryServer.getServerErrorResultCode(), message);
            }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java
@@ -22,18 +22,12 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.util.Iterator;
import java.util.TreeSet;
import org.forgerock.opendj.ldap.ByteStringBuilder;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.RDN;
import org.opends.server.util.StaticUtils;
/**
 * Handles the disk representation of LDAP data.
@@ -254,62 +248,6 @@
  }
  /**
   * Decode a DN value from its database key representation.
   *
   * @param dnKey The database key value of the DN.
   * @param prefix The DN to prefix the decoded DN value.
   * @return The decoded DN value.
   * @throws DirectoryException if an error occurs while decoding the DN value.
   * @see #dnToDNKey(DN, int)
   */
  public static DN dnFromDNKey(byte[] dnKey, DN prefix)
      throws DirectoryException
  {
    DN dn = prefix;
    boolean escaped = false;
    ByteStringBuilder buffer = new ByteStringBuilder();
    for (byte b : dnKey)
    {
      if (b == 0x5C)
      {
        escaped = true;
        continue;
      }
      else if (!escaped && b == 0x01)
      {
        buffer.append(0x01);
        escaped = false;
        continue;
      }
      else if (!escaped && b == 0x00)
      {
        if(buffer.length() > 0)
        {
          dn = dn.child(RDN.decode(buffer.toString()));
          buffer.clear();
        }
      }
      else
      {
        if(escaped)
        {
          buffer.append(0x5C);
          escaped = false;
        }
        buffer.append(b);
      }
    }
    if(buffer.length() > 0)
    {
      dn = dn.child(RDN.decode(buffer.toString()));
    }
    return dn;
  }
  /**
   * Find the length of bytes that represents the superior DN of the given
   * DN key. The superior DN is represented by the initial bytes of the DN key.
   *
@@ -334,17 +272,17 @@
   */
  public static int findDNKeyParent(byte[] dnKey, int offset, int length)
  {
    if(length == 0)
    if (length == 0)
    {
      // This is the root or base DN
      return -1;
    }
    // We will walk backwords through the buffer and find the first
    // unescaped comma
    for(int i = offset+length - 1; i >= offset; i--)
    // We will walk backwords through the buffer and
    // find the first unescaped NORMALIZED_RDN_SEPARATOR
    for (int i = offset+length - 1; i >= offset; i--)
    {
      if(dnKey[i] == 0x00 && i-1 >= offset && dnKey[i-1] != 0x5C)
      if (dnKey[i] == DN.NORMALIZED_RDN_SEPARATOR && i-1 >= offset && dnKey[i-1] != DN.NORMALIZED_ESC_BYTE)
      {
        return i;
      }
@@ -354,48 +292,24 @@
  /**
   * Create a DN database key from an entry DN.
   *
   * @param dn The entry DN.
   * @param prefixRDNs The number of prefix RDNs to remove from the encoded
   *                   representation.
   * @return A DatabaseEntry containing the key.
   * @see #dnFromDNKey(byte[], DN)
   */
  public static byte[] dnToDNKey(DN dn, int prefixRDNs)
  {
    StringBuilder buffer = new StringBuilder();
    for (int i = dn.size() - prefixRDNs - 1; i >= 0; i--)
    ByteStringBuilder builder = new ByteStringBuilder();
    int startSize = dn.size() - prefixRDNs - 1;
    for (int i = startSize; i >= 0; i--)
    {
      buffer.append('\u0000');
      formatRDNKey(dn.getRDN(i), buffer);
        builder.append(DN.NORMALIZED_RDN_SEPARATOR);
        dn.getRDN(i).toNormalizedByteString(builder);
    }
    return StaticUtils.getBytes(buffer.toString());
    return builder.toByteArray();
  }
  private static void formatRDNKey(RDN rdn, StringBuilder buffer)
  {
    if (!rdn.isMultiValued())
    {
      rdn.toNormalizedString(buffer);
    }
    else
    {
      TreeSet<String> rdnElementStrings = new TreeSet<String>();
      for (int i=0; i < rdn.getNumValues(); i++)
      {
        StringBuilder b2 = new StringBuilder();
        rdn.getNormalizedAVAString(i, b2);
        rdnElementStrings.add(b2.toString());
      }
      Iterator<String> iterator = rdnElementStrings.iterator();
      buffer.append(iterator.next().replace("\u0001", "\\\u0001"));
      while (iterator.hasNext())
      {
        buffer.append('\u0001');
        buffer.append(iterator.next().replace("\u0001", "\\\u0001"));
      }
    }
  }
}
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/RootContainer.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb;
@@ -233,7 +233,7 @@
    String databasePrefix;
    if(name == null || name.equals(""))
    {
      databasePrefix = baseDN.toNormalizedString();
      databasePrefix = baseDN.toIrreversibleReadableString();
    }
    else
    {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb.importLDIF;
@@ -746,7 +746,8 @@
        {
          // Create a temp entry container
          sourceEntryContainer = entryContainer;
          entryContainer = rootContainer.openEntryContainer(baseDN, baseDN.toNormalizedString() + "_importTmp");
          entryContainer = rootContainer.openEntryContainer(baseDN, baseDN.toIrreversibleReadableString()
              + "_importTmp");
        }
      }
    }
@@ -987,7 +988,7 @@
        needRegisterContainer.unlock();
        EntryContainer newEC = suffix.getEntryContainer();
        newEC.lock();
        newEC.setDatabasePrefix(baseDN.toNormalizedString());
        newEC.setDatabasePrefix(baseDN.toIrreversibleReadableString());
        newEC.unlock();
        rootContainer.registerEntryContainer(baseDN, newEC);
      }
@@ -4276,17 +4277,22 @@
    public boolean insert(DN dn, DatabaseEntry val, DatabaseEntry key)
        throws JebException
    {
      byte[] dnBytes = StaticUtils.getBytes(dn.toNormalizedString());
      int len = PackedInteger.getWriteIntLength(dnBytes.length);
      byte[] dataBytes = new byte[dnBytes.length + len];
      int pos = PackedInteger.writeInt(dataBytes, 0, dnBytes.length);
      System.arraycopy(dnBytes, 0, dataBytes, pos, dnBytes.length);
      // Use a compact representation for key
      byte[] dnBytesForKey = dn.toIrreversibleNormalizedByteString().toByteArray();
      key.setData(hashCode(dnBytesForKey));
      // Use a reversible representation for value
      byte[] dnBytesForValue = StaticUtils.getBytes(dn.toString());
      int len = PackedInteger.getWriteIntLength(dnBytesForValue.length);
      byte[] dataBytes = new byte[dnBytesForValue.length + len];
      int pos = PackedInteger.writeInt(dataBytes, 0, dnBytesForValue.length);
      System.arraycopy(dnBytesForValue, 0, dataBytes, pos, dnBytesForValue.length);
      val.setData(dataBytes);
      key.setData(hashCode(dnBytes));
      return insert(key, val, dnBytes);
      return insert(key, val, dnBytesForValue);
    }
    private boolean insert(DatabaseEntry key, DatabaseEntry val, byte[] dnBytes)
    private boolean insert(DatabaseEntry key, DatabaseEntry val, byte[] dnBytesForValue)
        throws JebException
    {
      Cursor cursor = null;
@@ -4302,9 +4308,9 @@
          {
            throw new JebException(LocalizableMessage.raw("Search DN cache failed."));
          }
          if (!isDNMatched(dns, dnBytes))
          if (!isDNMatched(dns, dnBytesForValue))
          {
            addDN(dns, cursor, dnBytes);
            addDN(dns, cursor, dnBytesForValue);
            return true;
          }
          return false;
@@ -4318,17 +4324,17 @@
    }
    /** Add the DN to the DNs as because of a hash collision. */
    private void addDN(DatabaseEntry val, Cursor cursor, byte[] dnBytes)
    private void addDN(DatabaseEntry val, Cursor cursor, byte[] dnBytesForValue)
        throws JebException
    {
      byte[] bytes = val.getData();
      int pLen = PackedInteger.getWriteIntLength(dnBytes.length);
      int totLen = bytes.length + pLen + dnBytes.length;
      int pLen = PackedInteger.getWriteIntLength(dnBytesForValue.length);
      int totLen = bytes.length + pLen + dnBytesForValue.length;
      byte[] newRec = new byte[totLen];
      System.arraycopy(bytes, 0, newRec, 0, bytes.length);
      int pos = bytes.length;
      pos = PackedInteger.writeInt(newRec, pos, dnBytes.length);
      System.arraycopy(dnBytes, 0, newRec, pos, dnBytes.length);
      pos = PackedInteger.writeInt(newRec, pos, dnBytesForValue.length);
      System.arraycopy(dnBytesForValue, 0, newRec, pos, dnBytesForValue.length);
      DatabaseEntry newVal = new DatabaseEntry(newRec);
      OperationStatus status = cursor.putCurrent(newVal);
      if (status != OperationStatus.SUCCESS)
@@ -4371,14 +4377,15 @@
    {
      Cursor cursor = null;
      DatabaseEntry key = new DatabaseEntry();
      byte[] dnBytes = StaticUtils.getBytes(dn.toNormalizedString());
      key.setData(hashCode(dnBytes));
      byte[] dnBytesForKey = dn.toIrreversibleNormalizedByteString().toByteArray();
      key.setData(hashCode(dnBytesForKey));
      try
      {
        cursor = dnCache.openCursor(null, CursorConfig.DEFAULT);
        DatabaseEntry dns = new DatabaseEntry();
        OperationStatus status = cursor.getSearchKey(key, dns, LockMode.DEFAULT);
        return status == OperationStatus.SUCCESS && isDNMatched(dns, dnBytes);
        byte[] dnBytesForValue = StaticUtils.getBytes(dn.toString());
        return status == OperationStatus.SUCCESS && isDNMatched(dns, dnBytesForValue);
      }
      finally
      {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/JebFormat.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.backends.pluggable;
@@ -146,7 +146,7 @@
  {
    if (!rdn.isMultiValued())
    {
      rdn.toNormalizedString(buffer);
      rdn.toString(buffer);
    }
    else
    {
@@ -155,7 +155,6 @@
      for (int i=0; i < rdn.getNumValues(); i++)
      {
        StringBuilder b2 = new StringBuilder();
        rdn.getNormalizedAVAString(i, b2);
        rdnElementStrings.add(b2.toString());
      }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/backends/pluggable/RootContainer.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.backends.pluggable;
@@ -419,7 +419,7 @@
    String databasePrefix;
    if(name == null || name.equals(""))
    {
      databasePrefix = baseDN.toNormalizedString();
      databasePrefix = baseDN.toIrreversibleReadableString();
    }
    else
    {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/AuthenticatedUsers.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.core;
@@ -268,8 +268,8 @@
    Entry oldEntry = op.getOriginalEntry();
    Entry newEntry = op.getUpdatedEntry();
    String oldDNString = oldEntry.getName().toNormalizedString();
    String newDNString = newEntry.getName().toNormalizedString();
    DN oldDN = oldEntry.getName();
    DN newDN = newEntry.getName();
    // Identify any client connections that may be authenticated
    // or authorized as the user whose entry has been modified
@@ -295,7 +295,7 @@
            authNDN = conn.getAuthenticationInfo().getAuthenticationDN();
            try
            {
              newAuthNDN = getNewAuthDN(authNDN, oldDNString, newDNString);
              newAuthNDN = authNDN.rename(oldDN, newDN);
            }
            catch (Exception e)
            {
@@ -308,7 +308,7 @@
            authZDN = conn.getAuthenticationInfo().getAuthorizationDN();
            try
            {
              newAuthZDN = getNewAuthDN(authZDN, oldDNString, newDNString);
              newAuthZDN = authZDN.rename(oldDN, newDN);
            }
            catch (Exception e)
            {
@@ -353,16 +353,5 @@
    }
    return PostResponse.continueOperationProcessing();
  }
  private DN getNewAuthDN(DN authDN, String oldDNString, String newDNString) throws DirectoryException
  {
    // FIXME once we move to the SDK:
    // Matt suggests we should be using the following code here:
    // return authDN.rename(oldDNString, newDNString);
    final StringBuilder builder = new StringBuilder(authDN.toNormalizedString());
    final int oldDNIndex = builder.lastIndexOf(oldDNString);
    builder.replace(oldDNIndex, builder.length(), newDNString);
    return DN.valueOf(builder.toString());
  }
}
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/EntryCacheConfigManager.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013-2014 ForgeRock AS.
 *      Portions Copyright 2013-2015 ForgeRock AS.
 */
package org.opends.server.core;
@@ -30,6 +30,7 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.util.Utils;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.server.ConfigurationAddListener;
@@ -76,9 +77,8 @@
  private SortedMap<Integer, EntryCache> cacheOrderMap =
      new TreeMap<Integer, EntryCache>();
  // The entry cache name to level map.
  private HashMap<String, Integer>
    cacheNameToLevelMap = new HashMap<String, Integer>();
  /** The entry cache name to level map. The key is a byte string representation of the name (DN). */
  private Map<ByteString,Integer> cacheNameToLevelMap = new HashMap<ByteString, Integer>();
  // Global entry cache monitor provider name.
  private static final String
@@ -255,19 +255,20 @@
      status = false;
    }
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty() &&
      (cacheNameToLevelMap.get(
       configuration.dn().toNormalizedString()) != null)) {
      int currentCacheLevel = cacheNameToLevelMap.get(
        configuration.dn().toNormalizedString());
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty())
    {
      final ByteString normDN = configuration.dn().toIrreversibleNormalizedByteString();
      if (cacheNameToLevelMap.containsKey(normDN)) {
        int currentCacheLevel = cacheNameToLevelMap.get(normDN);
      // Check if there any existing cache at the same level.
      if ((currentCacheLevel != configuration.getCacheLevel()) &&
        (cacheOrderMap.containsKey(configuration.getCacheLevel()))) {
        unacceptableReasons.add(
          ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE.get(
            configuration.dn(), configuration.getCacheLevel()));
        status = false;
        // Check if there any existing cache at the same level.
        if ((currentCacheLevel != configuration.getCacheLevel()) &&
          (cacheOrderMap.containsKey(configuration.getCacheLevel()))) {
          unacceptableReasons.add(
            ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE.get(
              configuration.dn(), configuration.getCacheLevel()));
          status = false;
        }
      }
    }
@@ -287,20 +288,20 @@
    // If we this entry cache is already installed and active it
    // should be present in the cache maps, if so use it.
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty() &&
      (cacheNameToLevelMap.get(
       configuration.dn().toNormalizedString()) != null)) {
      int currentCacheLevel = cacheNameToLevelMap.get(
        configuration.dn().toNormalizedString());
      entryCache = cacheOrderMap.get(currentCacheLevel);
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty()) {
      final ByteString normDN = configuration.dn().toIrreversibleNormalizedByteString();
      if (cacheNameToLevelMap.containsKey(normDN))
      {
        int currentCacheLevel = cacheNameToLevelMap.get(normDN);
        entryCache = cacheOrderMap.get(currentCacheLevel);
      // Check if the existing cache just shifted its level.
      if (currentCacheLevel != configuration.getCacheLevel()) {
        // Update the maps then.
        cacheOrderMap.remove(currentCacheLevel);
        cacheOrderMap.put(configuration.getCacheLevel(), entryCache);
        cacheNameToLevelMap.put(configuration.dn().toNormalizedString(),
          configuration.getCacheLevel());
        // Check if the existing cache just shifted its level.
        if (currentCacheLevel != configuration.getCacheLevel()) {
          // Update the maps then.
          cacheOrderMap.remove(currentCacheLevel);
          cacheOrderMap.put(configuration.getCacheLevel(), entryCache);
          cacheNameToLevelMap.put(normDN, configuration.getCacheLevel());
        }
      }
    }
@@ -484,7 +485,7 @@
      }
      entryCache.finalizeEntryCache();
      cacheOrderMap.remove(configuration.getCacheLevel());
      cacheNameToLevelMap.remove(configuration.dn().toNormalizedString());
      cacheNameToLevelMap.remove(configuration.dn().toIrreversibleNormalizedByteString());
      // Push any changes made to the cache order map.
      setCacheOrder(cacheOrderMap);
@@ -530,7 +531,7 @@
    // Add this entry cache to the current cache config maps.
    cacheOrderMap.put(configuration.getCacheLevel(), entryCache);
    cacheNameToLevelMap.put(configuration.dn().toNormalizedString(),
    cacheNameToLevelMap.put(configuration.dn().toIrreversibleNormalizedByteString(),
      configuration.getCacheLevel());
    // Push any changes made to the cache order map.
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/GroupManager.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2007-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.core;
@@ -804,30 +804,15 @@
    try
    {
      Set<Group<?>> groupSet = new HashSet<Group<?>>();
      groupInstances.removeSubtree(oldEntry.getName(), groupSet);
      String oldDNString = oldEntry.getName().toNormalizedString();
      String newDNString = newEntry.getName().toNormalizedString();
      final DN oldDN = oldEntry.getName();
      final DN newDN = newEntry.getName();
      groupInstances.removeSubtree(oldDN, groupSet);
      for (Group<?> group : groupSet)
      {
        StringBuilder builder = new StringBuilder(
                group.getGroupDN().toNormalizedString());
        int oldDNIndex = builder.lastIndexOf(oldDNString);
        builder.replace(oldDNIndex, builder.length(), newDNString);
        String groupDNString = builder.toString();
        DN groupDN;
        try
        {
          groupDN = DN.valueOf(groupDNString);
        }
        catch (DirectoryException de)
        {
          // Should not happen but if it does all we
          // can do here is debug log it and continue.
          logger.traceException(de);
          continue;
        }
        group.setGroupDN(groupDN);
        groupInstances.put(groupDN, group);
        final DN groupDN = group.getGroupDN();
        final DN renamedGroupDN = groupDN.rename(oldDN, newDN);
        group.setGroupDN(renamedGroupDN);
        groupInstances.put(renamedGroupDN, group);
      }
      if (!groupSet.isEmpty())
      {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/core/SubentryManager.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.core;
@@ -190,7 +190,7 @@
   * Add a given entry to this subentry manager.
   * @param entry to add.
   */
  private void addSubEntry(Entry entry) throws DirectoryException
  private void addSubentry(Entry entry) throws DirectoryException
  {
    SubEntry subEntry = new SubEntry(entry);
    SubtreeSpecification subSpec =
@@ -233,7 +233,7 @@
   * Remove a given entry from this subentry manager.
   * @param entry to remove.
   */
  private void removeSubEntry(Entry entry)
  private void removeSubentry(Entry entry)
  {
    lock.writeLock().lock();
    try
@@ -368,7 +368,7 @@
        {
          try
          {
            addSubEntry(entry);
            addSubentry(entry);
            // Notify change listeners.
            for (SubentryChangeListener changeListener :
@@ -708,7 +708,7 @@
      {
        try
        {
          addSubEntry(entry);
          addSubentry(entry);
          // Notify change listeners.
          for (SubentryChangeListener changeListener :
@@ -745,7 +745,7 @@
    {
      for (SubEntry subEntry : dit2SubEntry.getSubtree(entry.getName()))
      {
        removeSubEntry(subEntry.getEntry());
        removeSubentry(subEntry.getEntry());
        // Notify change listeners.
        for (SubentryChangeListener changeListener :
@@ -777,14 +777,14 @@
    {
      if (oldEntry.isSubentry() || oldEntry.isLDAPSubentry())
      {
        removeSubEntry(oldEntry);
        removeSubentry(oldEntry);
        notify = true;
      }
      if (newEntry.isSubentry() || newEntry.isLDAPSubentry())
      {
        try
        {
          addSubEntry(newEntry);
          addSubentry(newEntry);
          notify = true;
        }
        catch (Exception e)
@@ -819,31 +819,24 @@
    }
  }
  private void doPostModifyDN(Entry oldEntry, Entry newEntry)
  private void doPostModifyDN(final Entry oldEntry, final Entry newEntry)
  {
    String oldDNString = oldEntry.getName().toNormalizedString();
    String newDNString = newEntry.getName().toNormalizedString();
    lock.writeLock().lock();
    try
    {
      Collection<SubEntry> setToDelete =
              dit2SubEntry.getSubtree(oldEntry.getName());
      Collection<SubEntry> setToDelete = dit2SubEntry.getSubtree(oldEntry.getName());
      for (SubEntry subentry : setToDelete)
      {
        removeSubEntry(subentry.getEntry());
        oldEntry = subentry.getEntry();
        final Entry currentSubentry = subentry.getEntry();
        removeSubentry(currentSubentry);
        Entry renamedSubentry = null;
        try
        {
          StringBuilder builder = new StringBuilder(
              subentry.getEntry().getName().toNormalizedString());
          int oldDNIndex = builder.lastIndexOf(oldDNString);
          builder.replace(oldDNIndex, builder.length(),
                  newDNString);
          String subentryDNString = builder.toString();
          newEntry = subentry.getEntry().duplicate(false);
          newEntry.setDN(DN.valueOf(subentryDNString));
          addSubEntry(newEntry);
          renamedSubentry = currentSubentry.duplicate(false);
          final DN renamedDN = currentSubentry.getName().rename(oldEntry.getName(), newEntry.getName());
          renamedSubentry.setDN(renamedDN);
          addSubentry(renamedSubentry);
        }
        catch (Exception e)
        {
@@ -857,8 +850,7 @@
        {
          try
          {
            changeListener.handleSubentryModify(
                    oldEntry, newEntry);
            changeListener.handleSubentryModify(currentSubentry, renamedSubentry);
          }
          catch (Exception e)
          {
@@ -1017,18 +1009,14 @@
   * {@inheritDoc}
   */
  @Override
  public PreOperation doPreOperation(
          PreOperationModifyDNOperation modifyDNOperation)
  public PreOperation doPreOperation(PreOperationModifyDNOperation modifyDNOperation)
  {
    Entry oldEntry = modifyDNOperation.getOriginalEntry();
    Entry newEntry = modifyDNOperation.getUpdatedEntry();
    String oldDNString = oldEntry.getName().toNormalizedString();
    String newDNString = newEntry.getName().toNormalizedString();
    boolean hasSubentryWritePrivilege = false;
    lock.readLock().lock();
    try
    {
      final Entry oldEntry = modifyDNOperation.getOriginalEntry();
      Collection<SubEntry> setToDelete =
              dit2SubEntry.getSubtree(oldEntry.getName());
      for (SubEntry subentry : setToDelete)
@@ -1049,30 +1037,18 @@
            hasSubentryWritePrivilege = true;
          }
        }
        oldEntry = subentry.getEntry();
        try
        {
          StringBuilder builder = new StringBuilder(
              subentry.getEntry().getName().toNormalizedString());
          int oldDNIndex = builder.lastIndexOf(oldDNString);
          builder.replace(oldDNIndex, builder.length(),
                  newDNString);
          String subentryDNString = builder.toString();
          newEntry = subentry.getEntry().duplicate(false);
          newEntry.setDN(DN.valueOf(subentryDNString));
        }
        catch (Exception e)
        {
          // Shouldnt happen.
          logger.traceException(e);
        }
        for (SubentryChangeListener changeListener :
                changeListeners)
        final Entry newEntry = modifyDNOperation.getUpdatedEntry();
        final Entry currentSubentry = subentry.getEntry();
        final Entry renamedSubentry = currentSubentry.duplicate(false);
        final DN renamedDN = currentSubentry.getName().rename(oldEntry.getName(), newEntry.getName());
        renamedSubentry.setDN(renamedDN);
        for (SubentryChangeListener changeListener : changeListeners)
        {
          try
          {
            changeListener.checkSubentryModifyAcceptable(
                    oldEntry, newEntry);
            changeListener.checkSubentryModifyAcceptable(currentSubentry, renamedSubentry);
          }
          catch (DirectoryException de)
          {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProvider.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -73,8 +73,8 @@
  @Override()
  public Attribute getValues(Entry entry, VirtualAttributeRule rule)
  {
    String normDNString = entry.getName().toNormalizedString();
    return Attributes.create(rule.getAttributeType(), normDNString);
    String dnString = entry.getName().toString();
    return Attributes.create(rule.getAttributeType(), dnString);
  }
  /** {@inheritDoc} */
@@ -166,8 +166,7 @@
                              SearchOperation searchOperation,
                              boolean isPreIndexed)
  {
    return isSearchable(rule.getAttributeType(), searchOperation.getFilter(),
                        0);
    return isSearchable(rule.getAttributeType(), searchOperation.getFilter(), 0);
  }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/EntryUUIDVirtualAttributeProvider.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -81,10 +81,13 @@
  @Override()
  public Attribute getValues(Entry entry, VirtualAttributeRule rule)
  {
    String normDNString = entry.getName().toNormalizedString();
    String uuidString =
         UUID.nameUUIDFromBytes(getBytes(normDNString)).toString();
    return Attributes.create(rule.getAttributeType(), uuidString);
    return Attributes.create(rule.getAttributeType(), getUUIDString(entry));
  }
  private String getUUIDString(Entry entry)
  {
    ByteString normDN = entry.getName().toIrreversibleNormalizedByteString();
    return UUID.nameUUIDFromBytes(normDN.toByteArray()).toString();
  }
  /** {@inheritDoc} */
@@ -99,14 +102,10 @@
  @Override()
  public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value)
  {
    MatchingRule matchingRule =
        rule.getAttributeType().getEqualityMatchingRule();
    MatchingRule matchingRule = rule.getAttributeType().getEqualityMatchingRule();
    try
    {
      String normalizedDN = entry.getName().toNormalizedString();
      String uuidString =
           UUID.nameUUIDFromBytes(getBytes(normalizedDN)).toString();
      String uuidString = getUUIDString(entry);
      ByteString normValue = matchingRule.normalizeAttributeValue(value);
      return uuidString.equals(normValue.toString());
    }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProvider.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -260,10 +260,10 @@
    {
      // Check for nested groups to see if we need to keep track of returned entries
      List<DN> nestedGroupsDNs = group.getNestedGroupDNs();
      HashSet<String> returnedDNs = null;
      Set<ByteString> returnedDNs = null;
      if (!nestedGroupsDNs.isEmpty())
      {
        returnedDNs = new HashSet<String>();
        returnedDNs = new HashSet<ByteString>();
      }
      if (!returnGroupMembers(searchOperation, group.getMembers(), returnedDNs))
      {
@@ -289,7 +289,7 @@
   *
   * @param searchOperation the search operation being processed.
   * @param memberList the list of members of the group being processed.
   * @param returnedDNs a set to store the DNs of entries already returned,
   * @param returnedDNs a set to store the normalized DNs of entries already returned,
   *                    null if there's no need to track for entries.
   * @return  <CODE>true</CODE> if the caller should continue processing the
   *          search request and sending additional entries and references, or
@@ -299,7 +299,7 @@
   *          the entry to the client and the search should be terminated.
   */
  private boolean returnGroupMembers(SearchOperation searchOperation,
                                  MemberList memberList, Set<String> returnedDNs)
                                  MemberList memberList, Set<ByteString> returnedDNs)
          throws DirectoryException
  {
    DN baseDN = searchOperation.getBaseDN();
@@ -313,8 +313,9 @@
        if (e.matchesBaseAndScope(baseDN, scope) &&
            filter.matchesEntry(e))
        {
          if (returnedDNs == null
              || returnedDNs.add(e.getName().toNormalizedString()))
          // The set of returned DNs is only used for detecting set membership
          // so it's ok to use the irreversible representation of the DN
          if (returnedDNs == null || returnedDNs.add(e.getName().toIrreversibleNormalizedByteString()))
          {
            if (!searchOperation.returnEntry(e, null))
            {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.monitors;
@@ -148,8 +148,7 @@
    LinkedList<Attribute> attrs = new LinkedList<Attribute>();
    // Configuration DN
    attrs.add(Attributes.create(configDnType, String.valueOf(
            connectionHandler.getComponentEntryDN().toNormalizedString())));
    attrs.add(Attributes.create(configDnType, String.valueOf(connectionHandler.getComponentEntryDN().toString())));
    int numConnections = 0;
    LinkedList<ClientConnection> conns = new LinkedList<ClientConnection>(
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/plugins/EntryUUIDPlugin.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.plugins;
@@ -170,7 +170,7 @@
    // Construct a new UUID.  In order to make sure that UUIDs are consistent
    // when the same LDIF is generated on multiple servers, we'll base the UUID
    // on the byte representation of the normalized DN.
    byte[] dnBytes = getBytes(entry.getName().toNormalizedString());
    byte[] dnBytes = entry.getName().toIrreversibleNormalizedByteString().toByteArray();
    UUID uuid = UUID.nameUUIDFromBytes(dnBytes);
    Attribute uuidAttr = Attributes.create(entryUUIDType, uuid.toString());
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS.
 *      Portions Copyright 2011-2015 ForgeRock AS.
 *      Portions copyright 2011 profiq s.r.o.
 */
package org.opends.server.plugins;
@@ -875,8 +875,7 @@
        setupWriter();
        for(Map.Entry<DN,DN> mapEntry : modDNmap.entrySet())
        {
          writer.write(mapEntry.getKey().toNormalizedString() + "\t" +
                  mapEntry.getValue().toNormalizedString());
          writer.write(mapEntry.getKey().toString() + "\t" + mapEntry.getValue().toString());
          writer.newLine();
        }
        writer.flush();
@@ -904,7 +903,7 @@
        setupWriter();
        for (DN deletedEntryDN : deleteDNset)
        {
          writer.write(deletedEntryDN.toNormalizedString());
          writer.write(deletedEntryDN.toString());
          writer.newLine();
        }
        writer.flush();
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/EntryHistorical.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.plugin;
@@ -919,8 +919,7 @@
          entryDN);
    }
    String normDNString = entryDN.toNormalizedString();
    return UUID.nameUUIDFromBytes(getBytes(normDNString)).toString();
    return UUID.nameUUIDFromBytes(entryDN.toIrreversibleNormalizedByteString().toByteArray()).toString();
  }
}
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.plugin;
@@ -2225,7 +2225,7 @@
    if (markConflict)
    {
      Attribute attr =
          Attributes.create(attrType, targetDN.toNormalizedString());
          Attributes.create(attrType, targetDN.toString());
      newOp.addModification(new Modification(ModificationType.REPLACE, attr));
    }
    else
@@ -2954,7 +2954,7 @@
      {
        addConflict(msg);
        String conflictRDN =
            generateConflictRDN(entryUUID, msg.getDN().toNormalizedString());
            generateConflictRDN(entryUUID, msg.getDN().toString());
        msg.setDN(DN.valueOf(conflictRDN));
        numUnresolvedNamingConflicts.incrementAndGet();
        return false;
@@ -3054,7 +3054,7 @@
    // create new internal modify operation and run it.
    AttributeType attrType = DirectoryServer.getAttributeType(DS_SYNC_CONFLICT,
        true);
    Attribute attr = Attributes.create(attrType, conflictDN.toNormalizedString());
    Attribute attr = Attributes.create(attrType, conflictDN.toString());
    List<Modification> mods =
        newList(new Modification(ModificationType.REPLACE, attr));
@@ -3087,7 +3087,7 @@
   */
  private void addConflict(AddMsg msg) throws DecodeException
  {
    String normalizedDN = msg.getDN().toNormalizedString();
    String normalizedDN = msg.getDN().toString();
    // Generate an alert to let the administrator know that some
    // conflict could not be solved.
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.plugin;
@@ -852,16 +852,18 @@
   * Gets the Set of domain baseDN which are disabled for the external changelog.
   *
   * @return The Set of domain baseDNs which are disabled for the external changelog.
   * @throws DirectoryException
   *            if a problem occurs
   */
  public static Set<String> getExcludedChangelogDomains()
  public static Set<DN> getExcludedChangelogDomains() throws DirectoryException
  {
    final Set<String> disabledBaseDNs = new HashSet<String>(domains.size() + 1);
    disabledBaseDNs.add(DN_EXTERNAL_CHANGELOG_ROOT);
    final Set<DN> disabledBaseDNs = new HashSet<DN>(domains.size() + 1);
    disabledBaseDNs.add(DN.valueOf(DN_EXTERNAL_CHANGELOG_ROOT));
    for (LDAPReplicationDomain domain : domains.values())
    {
      if (!domain.isECLEnabled())
      {
        disabledBaseDNs.add(domain.getBaseDN().toNormalizedString());
        disabledBaseDNs.add(domain.getBaseDN());
      }
    }
    return disabledBaseDNs;
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/LightweightServerHandler.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server;
@@ -172,7 +172,7 @@
    final ReplicationServerDomain domain = replServerHandler.getDomain();
    attributes.add(Attributes.create("server-id", String.valueOf(serverId)));
    attributes.add(Attributes.create("domain-name",
        domain.getBaseDN().toNormalizedString()));
        domain.getBaseDN().toString()));
    attributes.add(Attributes.create("connected-to",
        replServerHandler.getMonitorInstanceName()));
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/MessageHandler.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server;
@@ -566,7 +566,7 @@
   */
  protected String getBaseDNString()
  {
    return baseDN.toNormalizedString();
    return baseDN.toString();
  }
  /**
@@ -643,7 +643,7 @@
    else
    {
      this.baseDN = baseDN;
      setDomain(!"cn=changelog".equals(baseDN.toNormalizedString())
      setDomain(!"cn=changelog".equals(baseDN.toIrreversibleReadableString())
          && isDataServer);
    }
  }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationDomainMonitor.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server;
@@ -154,7 +154,7 @@
      {
        try
        {
          String baseDN = domain.getBaseDN().toNormalizedString();
          String baseDN = domain.getBaseDN().toString();
          // Prevent out of band monitor responses from updating our pending
          // table until we are ready.
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server;
@@ -1279,16 +1279,16 @@
   * Returns the newest cookie value.
   *
   * @param excludedBaseDNs
   *          The list of baseDNs excluded from ECL.
   *          The set of baseDNs excluded from ECL.
   * @return the newest cookie value.
   */
  public MultiDomainServerState getNewestECLCookie(Set<String> excludedBaseDNs)
  public MultiDomainServerState getNewestECLCookie(Set<DN> excludedBaseDNs)
  {
    // Initialize start state for all running domains with empty state
    final MultiDomainServerState result = new MultiDomainServerState();
    for (ReplicationServerDomain rsDomain : getReplicationServerDomains())
    {
      if (!contains(excludedBaseDNs, rsDomain.getBaseDN().toNormalizedString()))
      if (!excludedBaseDNs.contains(rsDomain.getBaseDN()))
      {
        final ServerState latestDBServerState = rsDomain.getLatestServerState();
        if (!latestDBServerState.isEmpty())
@@ -1300,11 +1300,6 @@
    return result;
  }
  private boolean contains(Set<String> col, String elem)
  {
    return col != null && col.contains(elem);
  }
  /**
   * Gets the weight affected to the replication server.
   * <p>
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server;
@@ -2324,7 +2324,7 @@
    attributes.add(Attributes.create("replication-server-port",
        String.valueOf(localReplicationServer.getReplicationPort())));
    attributes.add(Attributes.create("domain-name",
        baseDN.toNormalizedString()));
        baseDN.toString()));
    attributes.add(Attributes.create("generation-id",
        baseDN + " " + generationId));
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
@@ -21,7 +21,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2014 ForgeRock AS
 *      Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.replication.server.changelog.file;
@@ -269,7 +269,7 @@
    {
      final List<Attribute> attributes = new ArrayList<Attribute>();
      create(attributes, "replicationServer-database",String.valueOf(serverId));
      create(attributes, "domain-name", baseDN.toNormalizedString());
      create(attributes, "domain-name", baseDN.toString());
      final CSNLimits limits = csnLimits;
      if (limits.oldestCSN != null)
      {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/DraftCNDB.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server.changelog.je;
@@ -88,7 +88,7 @@
    {
      final long changeNumber = record.getChangeNumber();
      DatabaseEntry key = new ReplicationDraftCNKey(changeNumber);
      DatabaseEntry data = new DraftCNData(changeNumber, record.getBaseDN().toNormalizedString(), record.getCSN());
      DatabaseEntry data = new DraftCNData(changeNumber, record.getBaseDN().toString(), record.getCSN());
      // Use a transaction so that we can override durability.
      Transaction txn = null;
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDB.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server.changelog.je;
@@ -293,7 +293,7 @@
    {
      final List<Attribute> attributes = new ArrayList<Attribute>();
      create(attributes, "replicationServer-database",String.valueOf(serverId));
      create(attributes, "domain-name", baseDN.toNormalizedString());
      create(attributes, "domain-name", baseDN.toString());
      final CSNLimits limits = csnLimits;
      if (limits.oldestCSN != null)
      {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/server/changelog/je/ReplicationDbEnv.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.server.changelog.je;
@@ -37,8 +37,6 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteStringBuilder;
import org.opends.server.replication.common.CSN;
import org.opends.server.replication.server.ChangelogState;
import org.opends.server.replication.server.ReplicationServer;
@@ -293,10 +291,10 @@
        }
        else if (prefix.equals(OFFLINE_TAG))
        {
          final String[] str = stringKey.split(FIELD_SEPARATOR, 3);
          final String[] str = stringData.split(FIELD_SEPARATOR, 3);
          long timestamp = toLong(str[0]);
          final int serverId = toInt(str[1]);
          final DN baseDN = DN.valueOf(str[2]);
          long timestamp = ByteString.wrap(entry.getValue()).asReader().getLong();
          if (logger.isTraceEnabled())
          {
            debug("has read replica offline: baseDN=" + baseDN + " serverId="
@@ -481,8 +479,9 @@
   */
  static Entry<String, String> toReplicaEntry(DN baseDN, int serverId)
  {
    final String key = serverId + FIELD_SEPARATOR + baseDN.toNormalizedString();
    return new SimpleImmutableEntry<String, String>(key, key);
    final String key = serverId + FIELD_SEPARATOR + baseDN.toIrreversibleReadableString();
    final String value = serverId + FIELD_SEPARATOR + baseDN.toString();
    return new SimpleImmutableEntry<String, String>(key, value);
  }
  /**
@@ -497,11 +496,10 @@
   */
  static Entry<byte[], byte[]> toGenIdEntry(DN baseDN, long generationId)
  {
    final String normDn = baseDN.toNormalizedString();
    final String key = GENERATION_ID_TAG + FIELD_SEPARATOR + normDn;
    final String key = GENERATION_ID_TAG + FIELD_SEPARATOR + baseDN.toIrreversibleReadableString();
    final String data = GENERATION_ID_TAG + FIELD_SEPARATOR + generationId
        + FIELD_SEPARATOR + normDn;
    return new SimpleImmutableEntry<byte[], byte[]>(toBytes(key),toBytes(data));
        + FIELD_SEPARATOR + baseDN.toString();
    return new SimpleImmutableEntry<byte[], byte[]>(toBytes(key), toBytes(data));
  }
  /**
@@ -513,9 +511,7 @@
   */
  static Entry<byte[], byte[]> toByteArray(Entry<String, String> entry)
  {
    return new SimpleImmutableEntry<byte[], byte[]>(
        toBytes(entry.getKey()),
        toBytes(entry.getValue()));
    return new SimpleImmutableEntry<byte[], byte[]>(toBytes(entry.getKey()), toBytes(entry.getValue()));
  }
  /**
@@ -530,10 +526,11 @@
   */
  static Entry<byte[], byte[]> toReplicaOfflineEntry(DN baseDN, CSN offlineCSN)
  {
    final byte[] key = toReplicaOfflineKey(baseDN, offlineCSN.getServerId());
    final ByteStringBuilder data = new ByteStringBuilder(8); // store a long
    data.append(offlineCSN.getTime());
    return new SimpleImmutableEntry<byte[], byte[]>(key, data.toByteArray());
    final int serverId = offlineCSN.getServerId();
    final byte[] key = toReplicaOfflineKey(baseDN, serverId);
    final byte[] data = toBytes(String.valueOf(offlineCSN.getTime()) + FIELD_SEPARATOR + serverId
        + FIELD_SEPARATOR + baseDN.toString());
    return new SimpleImmutableEntry<byte[], byte[]>(key, data);
  }
  /**
@@ -547,7 +544,7 @@
   */
  private static byte[] toReplicaOfflineKey(DN baseDN, int serverId)
  {
    return toBytes(OFFLINE_TAG + FIELD_SEPARATOR + serverId + FIELD_SEPARATOR + baseDN.toNormalizedString());
    return toBytes(OFFLINE_TAG + FIELD_SEPARATOR + serverId + FIELD_SEPARATOR + baseDN.toIrreversibleReadableString());
  }
  /** Returns an entry with the provided key and a null value. */
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/service/ReplicationBroker.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.service;
@@ -2117,7 +2117,7 @@
    if (heartbeatInterval > 0)
    {
      heartbeatMonitor = new HeartbeatMonitor(getServerId(), rs.getServerId(),
          getBaseDN().toNormalizedString(), rs.session, heartbeatInterval);
          getBaseDN().toString(), rs.session, heartbeatInterval);
      heartbeatMonitor.start();
    }
  }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/replication/service/ReplicationDomain.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.replication.service;
@@ -531,7 +531,7 @@
   */
  public String getBaseDNString()
  {
    return getBaseDN().toNormalizedString();
    return getBaseDN().toString();
  }
  /**
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.schema;
@@ -158,7 +158,7 @@
      {
        // This locale is not supported by JVM.
        logger.error(WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE,
                collation, configuration.dn().toNormalizedString(), languageTag);
                collation, configuration.dn().toString(), languageTag);
      }
    }
@@ -284,7 +284,7 @@
      {
        LocalizableMessage msg =
            WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE.get(
                collation, configuration.dn().toNormalizedString(),
                collation, configuration.dn().toString(),
                languageTag);
        unacceptableReasons.add(msg);
        configAcceptable = false;
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tasks/ImportTask.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2013-2014 ForgeRock AS
 *      Portions Copyright 2013-2015 ForgeRock AS
 */
package org.opends.server.tasks;
@@ -346,7 +346,7 @@
        StringBuilder builder = new StringBuilder();
        for(DN dn : backend.getBaseDNs())
        {
          builder.append(dn.toNormalizedString());
          builder.append(dn.toString());
          builder.append(" ");
        }
        LocalizableMessage message = ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND.get(
@@ -370,14 +370,14 @@
          {
            // The include branches span across multiple backends.
            LocalizableMessage message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
                includeBranch.toNormalizedString(), backend.getBackendID());
                includeBranch.toString(), backend.getBackendID());
            throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
          }
        }
        else
        {
          // The include branch is not associated with any backend.
          LocalizableMessage message = ERR_NO_BACKENDS_FOR_BASE.get(includeBranch.toNormalizedString());
          LocalizableMessage message = ERR_NO_BACKENDS_FOR_BASE.get(includeBranch.toString());
          throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
        }
      }
@@ -395,7 +395,7 @@
      if (!Backend.handlesEntry(includeBranch, defaultIncludeBranches, excludeBranches))
      {
        LocalizableMessage message = ERR_LDIFIMPORT_INVALID_INCLUDE_BASE.get(
            includeBranch.toNormalizedString(), backend.getBackendID());
            includeBranch.toString(), backend.getBackendID());
        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
      }
    }
@@ -539,11 +539,11 @@
          backend.getBaseDNs().length > 1 && !clearBackend)
      {
        StringBuilder builder = new StringBuilder();
        builder.append(backend.getBaseDNs()[0].toNormalizedString());
        builder.append(backend.getBaseDNs()[0].toString());
        for(int i = 1; i < backend.getBaseDNs().length; i++)
        {
          builder.append(" / ");
          builder.append(backend.getBaseDNs()[i].toNormalizedString());
          builder.append(backend.getBaseDNs()[i].toString());
        }
        logger.error(ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND, builder, ATTR_IMPORT_CLEAR_BACKEND);
        return TaskState.STOPPED_BY_ERROR;
@@ -564,8 +564,7 @@
          else if(backend != locatedBackend)
          {
            // The include branches span across multiple backends.
            logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch
                .toNormalizedString(), backend.getBackendID());
            logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch.toString(), backend.getBackendID());
            return TaskState.STOPPED_BY_ERROR;
          }
        }
@@ -640,7 +639,7 @@
        if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
                                   excludeBranches))
        {
          logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch.toNormalizedString(), backend.getBackendID());
          logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch.toString(), backend.getBackendID());
          return TaskState.STOPPED_BY_ERROR;
        }
      }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/DBTest.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2013-2014 ForgeRock AS
 *      Portions Copyright 2013-2015 ForgeRock AS
 */
package org.opends.server.tools;
@@ -74,7 +74,6 @@
import static com.forgerock.opendj.cli.Utils.*;
import static org.opends.messages.ToolMessages.*;
import static org.opends.server.backends.jeb.JebFormat.*;
import static org.opends.server.util.StaticUtils.*;
/**
@@ -653,7 +652,7 @@
      for(EntryContainer ec : rc.getEntryContainers())
      {
        builder.startRow();
        builder.appendCell(ec.getBaseDN().toNormalizedString());
        builder.appendCell(ec.getBaseDN().toString());
        builder.appendCell(ec.getDatabasePrefix());
        builder.appendCell(ec.getEntryCount());
        count++;
@@ -750,7 +749,7 @@
        if(ec == null)
        {
          printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get(
              base.toNormalizedString(), backend.getBackendID()));
              base.toString(), backend.getBackendID()));
          return 1;
        }
@@ -761,7 +760,7 @@
        for(EntryContainer ec : rc.getEntryContainers())
        {
          builder.startRow();
          builder.appendCell("Base DN: " + ec.getBaseDN().toNormalizedString());
          builder.appendCell("Base DN: " + ec.getBaseDN().toString());
          count = appendDatabaseContainerRows(builder, ec, count);
        }
      }
@@ -922,7 +921,7 @@
      if(ec == null)
      {
        printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get(
            base.toNormalizedString(), backend.getBackendID()));
            base.toString(), backend.getBackendID()));
        return 1;
      }
@@ -1109,7 +1108,7 @@
      if(ec == null)
      {
        printMessage(ERR_DBTEST_NO_ENTRY_CONTAINERS_FOR_BASE_DN.get(
            base.toNormalizedString(), backend.getBackendID()));
            base.toString(), backend.getBackendID()));
        return 1;
      }
@@ -1130,7 +1129,7 @@
      if(databaseContainer == null)
      {
        printMessage(ERR_DBTEST_NO_DATABASE_CONTAINERS_FOR_NAME.get(
            databaseName.getValue(), base.toNormalizedString(),
            databaseName.getValue(), base.toString(),
            backend.getBackendID()));
        return 1;
      }
@@ -1253,7 +1252,7 @@
              {
                try
                {
                  formatedKey = dnFromDNKey(key.getData(), ec.getBaseDN()).toNormalizedString();
                  formatedKey = ByteString.valueOf(key.getData()).toHexString() + ec.getBaseDN();
                  keyLabel = INFO_LABEL_DBTEST_ENTRY_DN.get();
                }
                catch(Exception e)
@@ -1489,8 +1488,7 @@
        || databaseContainer instanceof DN2URI)
    {
      // Encode the value as a DN
      return StaticUtils.getBytes(
          DN.valueOf(value).toNormalizedString());
      return DN.valueOf(value).toIrreversibleNormalizedByteString().toByteArray();
    }
    else if(databaseContainer instanceof ID2Entry)
    {
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/ImportLDIF.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS.
 *      Portions Copyright 2011-2015 ForgeRock AS.
 */
package org.opends.server.tools;
@@ -1258,11 +1258,11 @@
        !clearBackend.isPresent())
    {
      StringBuilder builder = new StringBuilder();
      builder.append(backend.getBaseDNs()[0].toNormalizedString());
      builder.append(backend.getBaseDNs()[0].toString());
      for(int i = 1; i < backend.getBaseDNs().length; i++)
      {
        builder.append(" / ");
        builder.append(backend.getBaseDNs()[i].toNormalizedString());
        builder.append(backend.getBaseDNs()[i].toString());
      }
      LocalizableMessage message = ERR_LDIFIMPORT_MISSING_CLEAR_BACKEND.get(
              builder, clearBackend.getLongIdentifier());
@@ -1306,7 +1306,7 @@
        if (! Backend.handlesEntry(includeBranch, defaultIncludeBranches,
                                   excludeBranches))
        {
          logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch.toNormalizedString(), backendID.getValue());
          logger.error(ERR_LDIFIMPORT_INVALID_INCLUDE_BASE, includeBranch.toString(), backendID.getValue());
          return 1;
        }
      }
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/DN.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.types;
@@ -37,6 +37,7 @@
import org.forgerock.opendj.ldap.ByteStringBuilder;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.util.Reject;
import org.opends.server.core.DirectoryServer;
import static org.forgerock.util.Reject.*;
@@ -70,7 +71,14 @@
   */
  public static final DN NULL_DN = new DN();
  /** RDN separator for normalized byte string of a DN. */
  public static final byte NORMALIZED_RDN_SEPARATOR = 0x00;
  /** AVA separator for normalized byte string of a DN. */
  public static final byte NORMALIZED_AVA_SEPARATOR = 0x01;
  /** Escape byte for normalized byte string of a DN. */
  public static final byte NORMALIZED_ESC_BYTE = 0x02;
  /**
   * The serial version identifier required to satisfy the compiler
@@ -95,8 +103,8 @@
  /** The string representation of this DN. */
  private String dnString;
  /** The normalized string representation of this DN. */
  private String normalizedDN;
  /** The irreversible normalized byte string representation of this DN. */
  private ByteString normalizedDN;
@@ -251,6 +259,38 @@
    }
  }
  /**
   * Returns a copy of this DN whose parent DN, {@code fromDN}, has been renamed
   * to the new parent DN, {@code toDN}. If this DN is not subordinate or equal
   * to {@code fromDN} then this DN is returned (i.e. the DN is not renamed).
   *
   * @param fromDN
   *          The old parent DN.
   * @param toDN
   *          The new parent DN.
   * @return The renamed DN, or this DN if no renaming was performed.
   */
  public DN rename(final DN fromDN, final DN toDN)
  {
    Reject.ifNull(fromDN, toDN);
    if (!isDescendantOf(fromDN))
    {
      return this;
    }
    else if (equals(fromDN))
    {
      return toDN;
    }
    else
    {
      final int sizeOfRdns = size() - fromDN.size();
      RDN[] childRdns = new RDN[sizeOfRdns];
      System.arraycopy(rdnComponents, 0, childRdns, 0, sizeOfRdns);
      return toDN.concat(childRdns);
    }
  }
  /**
@@ -587,6 +627,7 @@
      while (dnReader.remaining() > 0 && (b = dnReader.get()) == ' ')
      {}
      if(b == ' ')
      {
        // This means that we hit the end of the value before
@@ -2652,13 +2693,10 @@
   * Retrieves a normalized representation of the DN with the provided
   * components.
   *
   * @param  rdnComponents  The RDN components for which to obtain the
   *                        normalized string representation.
   *
   * @return  The normalized string representation of the provided RDN
   *          components.
   */
  private static String normalize(RDN[] rdnComponents)
  public String toIrreversibleReadableString()
  {
    if (rdnComponents.length == 0)
    {
@@ -2666,68 +2704,52 @@
    }
    StringBuilder buffer = new StringBuilder();
    rdnComponents[0].toNormalizedString(buffer);
    rdnComponents[0].toNormalizedReadableString(buffer);
    for (int i=1; i < rdnComponents.length; i++)
    {
      buffer.append(',');
      rdnComponents[i].toNormalizedString(buffer);
      rdnComponents[i].toNormalizedReadableString(buffer);
    }
    return buffer.toString();
  }
  /**
   * Retrieves a normalized string representation of this DN. This method should
   * be used over {@link #toString()} when the resulting String is to be used as
   * a key in a Map.
   * Returns the irreversible normalized byte string representation of a DN,
   * suitable for equality and comparisons, and providing a natural hierarchical
   * ordering, but not usable as a valid DN nor reversible to a valid DN.
   * <p>
   * Normalization involves:
   * <ol>
   * <li>sorting AVAs (e.g. "sn=swift+cn=matt" is greater than
   * "cn=matt+sn=swift")</li>
   * <li>normalizing attribute names (e.g. "commonName" is converted to "cn")
   * </li>
   * <li>normalizing attribute values (e.g. converting to lowercase)</li>
   * </ol>
   * Where AVA stands for "Attribute Value Assertion".
   * <p>
   * Remember that:
   * <ul>
   * <li>a DN is made of one or several RDNs</li>
   * <li>an RDN is made of one or several AVA</li>
   * <li>an AVA is a attribute type and an attribute value</li>
   * </ul>
   * This representation should be used only when a byte string representation
   * is needed and when no reversibility to a valid DN is needed. Always consider
   * using a {@code CompactDn} as an alternative.
   *
   * @return A normalized string representation of this DN.
   * @return The normalized byte string representation of the provided DN, not
   *         usable as a valid DN
   */
  public String toNormalizedString()
  public ByteString toIrreversibleNormalizedByteString()
  {
    if(normalizedDN == null)
    if (normalizedDN == null)
    {
      normalizedDN = normalize(this.rdnComponents);
      if (numComponents == 0)
      {
        normalizedDN = ByteString.empty();
      }
      else
      {
        final ByteStringBuilder builder = new ByteStringBuilder();
        rdnComponents[numComponents - 1].toNormalizedByteString(builder);
        for (int i = numComponents - 2; i >= 0; i--)
        {
          builder.append(NORMALIZED_RDN_SEPARATOR);
          rdnComponents[i].toNormalizedByteString(builder);
        }
        normalizedDN = builder.toByteString();
      }
    }
    return normalizedDN;
  }
  /**
   * Appends a normalized string representation of this DN to the
   * provided buffer.
   *
   * @param  buffer  The buffer to which the information should be
   *                 appended.
   */
  public void toNormalizedString(StringBuilder buffer)
  {
    buffer.append(toNormalizedString());
  }
  /**
   * Compares this DN with the provided DN based on a natural order. This order
   * will be first hierarchical (ancestors will come before descendants) and
opendj-sdk/opendj3-server-dev/src/server/org/opends/server/types/RDN.java
@@ -22,10 +22,16 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2013-2014 ForgeRock AS
 *      Portions Copyright 2013-2015 ForgeRock AS
 */
package org.opends.server.types;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.util.*;
import org.forgerock.i18n.LocalizableMessage;
@@ -55,6 +61,8 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  private static final char HEX_STRING_SEPARATOR = '%';
  /** The set of attribute types for the elements in this RDN. */
  private AttributeType[] attributeTypes;
@@ -1002,7 +1010,7 @@
  {
    if (normalizedRDN == null)
    {
      toNormalizedString(new StringBuilder());
      toNormalizedReadableString(new StringBuilder());
    }
    return normalizedRDN;
  }
@@ -1015,7 +1023,7 @@
   *
   * @param  buffer  The buffer to which to append the information.
   */
  public void toNormalizedString(StringBuilder buffer)
  void toNormalizedReadableString(StringBuilder buffer)
  {
    if (normalizedRDN != null)
    {
@@ -1023,25 +1031,24 @@
      return;
    }
    boolean bufferEmpty = (buffer.length() == 0);
    boolean providedBufferIsEmpty = (buffer.length() == 0);
    if (attributeNames.length == 1)
    {
      getNormalizedAVAString(0, buffer);
      normalizeAVAToReadableString(0, buffer);
    }
    else
    {
      // normalization sorts RDNs alphabetically
      SortedSet<String> rdnElementStrings = new TreeSet<String>();
      // Normalization sorts RDNs alphabetically
      SortedSet<String> avaStrings = new TreeSet<String>();
      for (int i=0; i < attributeNames.length; i++)
      {
        StringBuilder b2 = new StringBuilder();
        getNormalizedAVAString(i, b2);
        rdnElementStrings.add(b2.toString());
        StringBuilder builder = new StringBuilder();
        normalizeAVAToReadableString(i, builder);
        avaStrings.add(builder.toString());
      }
      Iterator<String> iterator = rdnElementStrings.iterator();
      Iterator<String> iterator = avaStrings.iterator();
      buffer.append(iterator.next());
      while (iterator.hasNext())
      {
@@ -1050,40 +1057,167 @@
      }
    }
    if (bufferEmpty)
    if (providedBufferIsEmpty)
    {
      normalizedRDN = buffer.toString();
    }
  }
  /**
   * Adds a normalized byte string representation of this RDN to the provided builder.
   *
   * @param builder
   *           Builder to add this representation to.
   * @return the builder
   */
  public ByteStringBuilder toNormalizedByteString(ByteStringBuilder builder) {
    if (attributeNames.length == 1)
    {
      normalizeAVAToByteString(0, builder);
    }
    else
    {
      // Normalization sorts RDNs
      SortedSet<ByteString> avaStrings = new TreeSet<ByteString>();
      for (int i = 0; i < attributeNames.length; i++)
      {
        ByteStringBuilder b = new ByteStringBuilder();
        normalizeAVAToByteString(i, b);
        avaStrings.add(b.toByteString());
      }
      Iterator<ByteString> iterator = avaStrings.iterator();
      builder.append(iterator.next());
      while (iterator.hasNext())
      {
        builder.append(DN.NORMALIZED_AVA_SEPARATOR);
        builder.append(iterator.next());
      }
    }
    return builder;
  }
  /**
   * Adds a normalized byte string representation of the AVA corresponding to provided position
   * in this RDN to the provided builder.
   *
   * @param position
   *           Position of AVA in this RDN
   * @param builder
   *           Builder to add the representation to.
   * @return the builder
   */
  ByteStringBuilder normalizeAVAToByteString(int position, final ByteStringBuilder builder)
  {
    builder.append(attributeTypes[position].getNormalizedPrimaryNameOrOID());
    builder.append("=");
    final ByteString value = getEqualityNormalizedValue(position);
    if (value.length() > 0)
    {
      builder.append(escapeBytes(value));
    }
    return builder;
  }
  /**
   * Return a new byte string with bytes 0x00, 0x01 and 0x02 escaped.
   * <p>
   * These bytes are reserved to represent respectively the RDN separator, the
   * AVA separator and the escape byte in a normalized byte string.
   */
  private ByteString escapeBytes(final ByteString value)
  {
    if (!needEscaping(value))
    {
      return value;
    }
    final ByteStringBuilder builder = new ByteStringBuilder();
    for (int i = 0; i < value.length(); i++)
    {
      final byte b = value.byteAt(i);
      if (isByteToEscape(b))
      {
        builder.append(DN.NORMALIZED_ESC_BYTE);
      }
      builder.append(b);
    }
    return builder.toByteString();
  }
  private boolean needEscaping(final ByteString value)
  {
    boolean needEscaping = false;
    for (int i = 0; i < value.length(); i++)
    {
      final byte b = value.byteAt(i);
      if (isByteToEscape(b))
      {
        needEscaping = true;
        break;
      }
    }
    return needEscaping;
  }
  private boolean isByteToEscape(final byte b)
  {
    return b == DN.NORMALIZED_RDN_SEPARATOR || b == DN.NORMALIZED_AVA_SEPARATOR || b == DN.NORMALIZED_ESC_BYTE;
  }
  /**
   * Appends a normalized string representation of this RDN to the
   * provided buffer.
   *
   * @param  pos  The position of the attribute type and value to
   * @param  position  The position of the attribute type and value to
   *              retrieve.
   * @param  buffer  The buffer to which to append the information.
   * @param  builder  The buffer to which to append the information.
   * @return the builder
   */
  public void getNormalizedAVAString(int pos, StringBuilder buffer)
  private StringBuilder normalizeAVAToReadableString(int position, StringBuilder builder)
  {
      AttributeType type = attributeTypes[pos];
      buffer.append(type.getNormalizedPrimaryNameOrOID());
      buffer.append('=');
      builder.append(attributeTypes[position].getNormalizedPrimaryNameOrOID());
      builder.append('=');
      ByteString value = attributeValues[pos];
      try
      ByteString value = getEqualityNormalizedValue(position);
      if (value.length() == 0)
      {
        MatchingRule rule = type.getEqualityMatchingRule();
        ByteString normValue = rule.normalizeAttributeValue(value);
        buffer.append(getDNValue(normValue));
        return builder;
      }
      catch (Exception e)
      final boolean hasAttributeName = attributeTypes[position].getPrimaryName() != null;
      final boolean isHumanReadable = attributeTypes[position].getSyntax().isHumanReadable();
      if (!hasAttributeName || !isHumanReadable)
      {
        logger.traceException(e);
        buffer.append(getDNValue(value));
        builder.append(value.toPercentHexString());
      }
      else
      {
        // try to decode value as UTF-8 string
        final CharBuffer buffer = CharBuffer.allocate(value.length());
        final CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT);
        if (value.copyTo(buffer, decoder))
        {
          try
          {
            // URL encoding encodes space char as '+' instead of using hex code
            final String val = URLEncoder.encode(buffer.toString(), "UTF-8").replaceAll("\\+", "%20");
            builder.append(val);
          }
          catch (UnsupportedEncodingException e)
          {
            // should never happen
            builder.append(value.toPercentHexString());
          }
        }
        else
        {
          builder.append(value.toPercentHexString());
        }
      }
      return builder;
  }
  /**
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestImportJob.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb;
@@ -245,6 +245,7 @@
    tempDir = TestCaseUtils.createTemporaryDirectory("jebimporttest");
    homeDirName = tempDir.getAbsolutePath();
    System.out.println(homeDirName.toString());
    EnvManager.createHomeDir(homeDirName);
@@ -291,7 +292,7 @@
  public void cleanUp() throws Exception
  {
    TestCaseUtils.disableBackend(beID);
    TestCaseUtils.deleteDirectory(tempDir);
    //TestCaseUtils.deleteDirectory(tempDir);
  }
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestJebFormat.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.backends.jeb;
@@ -41,6 +41,8 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
import static org.opends.server.backends.jeb.JebFormat.*;
import static org.opends.server.util.StaticUtils.*;
import static org.testng.Assert.*;
@@ -429,8 +431,7 @@
   */
  @Test()
  public void testEntryToAndFromDatabase() throws Exception {
    // Make sure that the server is up and running.
    TestCaseUtils.startServer();
    ensureTheServerIsUpAndRunning();
    // Convert the test LDIF string to a byte array
    byte[] originalLDIFBytes = StaticUtils.getBytes(ldifString);
@@ -501,8 +502,7 @@
   */
  @Test()
  public void testEntryToAndFromDatabaseV1() throws Exception {
    // Make sure that the server is up and running.
    TestCaseUtils.startServer();
    ensureTheServerIsUpAndRunning();
    // Convert the test LDIF string to a byte array
    byte[] originalLDIFBytes = StaticUtils.getBytes(ldifString);
@@ -551,8 +551,7 @@
  @Test(dataProvider = "encodeConfigs")
  public void testEntryToAndFromDatabaseV2(EntryEncodeConfig config)
         throws Exception {
    // Make sure that the server is up and running.
    TestCaseUtils.startServer();
    ensureTheServerIsUpAndRunning();
    // Convert the test LDIF string to a byte array
    byte[] originalLDIFBytes = StaticUtils.getBytes(ldifString);
@@ -583,8 +582,7 @@
  @Test(dataProvider = "encodeConfigs")
  public void testEntryToAndFromDatabaseV3(EntryEncodeConfig config)
         throws Exception {
    // Make sure that the server is up and running.
    TestCaseUtils.startServer();
    ensureTheServerIsUpAndRunning();
    // Convert the test LDIF string to a byte array
    byte[] originalLDIFBytes = StaticUtils.getBytes(ldifString);
@@ -605,4 +603,30 @@
    }
    reader.close();
  }
  @DataProvider
  private Object[][] findDnKeyParentData()
  {
    return new Object[][]
    {
      // dn, expected length of parent
      { "dc=example", 0 },
      { "dc=example,dc=com", 7 },
      { "dc=example,dc=com\\,org", 11 },
    };
  }
  @Test(dataProvider="findDnKeyParentData")
  public void testFindDnKeyParent(String dn, int expectedLength) throws Exception
  {
    ensureTheServerIsUpAndRunning();
    byte[] dnKey = dnToDNKey(DN.valueOf(dn), 0);
    assertThat(findDNKeyParent(dnKey)).isEqualTo(expectedLength);
  }
  private void ensureTheServerIsUpAndRunning() throws Exception
  {
    TestCaseUtils.startServer();
  }
}
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.core;
@@ -587,7 +587,7 @@
        buffer.append("___");
      }
      String ndn = dn.toNormalizedString();
      String ndn = dn.toIrreversibleReadableString();
      for (int i=0; i < ndn.length(); i++)
      {
        char c = ndn.charAt(i);
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/core/SubentryManagerTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.core;
@@ -403,7 +403,7 @@
  {
    InternalClientConnection conn = getRootConnection();
    List<RawModification> mods = newRawModifications(DELETE, attrType);
    ModifyOperation modifyOperation = conn.processModify(ByteString.valueOf(e.getName().toNormalizedString()), mods);
    ModifyOperation modifyOperation = conn.processModify(ByteString.valueOf(e.getName().toString()), mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
  }
@@ -411,7 +411,7 @@
  {
    InternalClientConnection conn = getRootConnection();
    List<RawModification> mods = newRawModifications(REPLACE, attrType, newValue);
    ModifyOperation modifyOperation = conn.processModify(ByteString.valueOf(e.getName().toNormalizedString()), mods);
    ModifyOperation modifyOperation = conn.processModify(ByteString.valueOf(e.getName().toString()), mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
  }
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -133,7 +133,7 @@
    {
      assertTrue(!a.isEmpty());
      assertEquals(a.size(), 1);
      assertTrue(a.contains(ByteString.valueOf(entryDN.toNormalizedString())));
      assertTrue(a.contains(ByteString.valueOf(entryDN.toString())));
    }
  }
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryUUIDVirtualAttributeProviderTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2014 ForgeRock AS
 *      Portions Copyright 2011-2015 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -97,7 +97,7 @@
      new Object[] { DN.valueOf("cn=schema") },
      new Object[] { DN.valueOf("cn=tasks") },
      new Object[] { DN.valueOf("cn=monitor") },
      new Object[] { DN.valueOf("cn=backups") }
      new Object[] { DN.valueOf("cn=backups") },
    };
  }
@@ -116,8 +116,7 @@
  public void testGetEntry(DN entryDN)
         throws Exception
  {
    String uuidString = UUID.nameUUIDFromBytes(
                             getBytes(entryDN.toNormalizedString())).toString();
    String uuidString = UUID.nameUUIDFromBytes(entryDN.toIrreversibleNormalizedByteString().toByteArray()).toString();
    Entry e = DirectoryServer.getEntry(entryDN);
    assertNotNull(e);
@@ -294,8 +293,7 @@
  public void testSearchEntryUUIDAttrInMatchingFilter(DN entryDN)
         throws Exception
  {
    String uuidString = UUID.nameUUIDFromBytes(
                             getBytes(entryDN.toNormalizedString())).toString();
    String uuidString = UUID.nameUUIDFromBytes(entryDN.toIrreversibleNormalizedByteString().toByteArray()).toString();
    final SearchRequest request = newSearchRequest(entryDN, SearchScope.BASE_OBJECT, "(entryUUID=" + uuidString + ")")
        .addAttribute("entryuuid");
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestBindResponseProtocolOp.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.protocols.ldap;
@@ -118,7 +118,8 @@
      assertTrue(protocolOp instanceof BindResponseProtocolOp);
      BindResponseProtocolOp bindResponse = (BindResponseProtocolOp)protocolOp;
      assertTrue(bindResponse.getResultCode() == okCode.intValue());
      assertTrue(bindResponse.getMatchedDN().toNormalizedString().equals(responseDn.toNormalizedString()));
      assertTrue(bindResponse.getMatchedDN().toIrreversibleNormalizedByteString()
          .equals(responseDn.toIrreversibleNormalizedByteString()));
      assertTrue(bindResponse.getErrorMessage().toString().equals(message.toString()));
      assertNull(bindResponse.getReferralURLs());
      assertNull(bindResponse.getServerSASLCredentials());
@@ -165,7 +166,8 @@
      assertTrue(protocolOp instanceof BindResponseProtocolOp);
      BindResponseProtocolOp bindResponse = (BindResponseProtocolOp)protocolOp;
      assertTrue(bindResponse.getResultCode() == okCode.intValue());
      assertTrue(bindResponse.getMatchedDN().toNormalizedString().equals(responseDn.toNormalizedString()));
      assertTrue(bindResponse.getMatchedDN().toIrreversibleNormalizedByteString().equals(
          responseDn.toIrreversibleNormalizedByteString()));
      assertTrue(bindResponse.getErrorMessage().toString().equals(message.toString()));
      assertNull(bindResponse.getReferralURLs());
      assertNull(bindResponse.getServerSASLCredentials());
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestDN.java
@@ -22,18 +22,22 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2012-2014 ForgeRock AS
 *      Portions Copyright 2012-2015 ForgeRock AS
 */
package org.opends.server.types;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteStringBuilder;
import java.util.ArrayList;
import static org.assertj.core.api.Assertions.*;
import static org.testng.Assert.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.util.Platform;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
@@ -53,69 +57,70 @@
  @DataProvider(name = "testDNs")
  public Object[][] createData() {
    return new Object[][] {
        { "", "", "" },
        { "   ", "", "" },
        { "cn=", "cn=", "cn=" },
        { "cn= ", "cn=", "cn=" },
        { "cn =", "cn=", "cn=" },
        { "cn = ", "cn=", "cn=" },
        { "dc=com", "dc=com", "dc=com" },
        { "dc=com+o=com", "dc=com+o=com", "dc=com+o=com" },
        { "DC=COM", "dc=com", "DC=COM" },
        { "dc = com", "dc=com", "dc=com" },
        { " dc = com ", "dc=com", "dc=com" },
        { "dc=example,dc=com", "dc=example,dc=com",
            "dc=example,dc=com" },
        { "dc=example, dc=com", "dc=example,dc=com",
            "dc=example,dc=com" },
        { "dc=example ,dc=com", "dc=example,dc=com",
            "dc=example,dc=com" },
        { "dc =example , dc  =   com", "dc=example,dc=com",
            "dc=example,dc=com" },
        { "givenName=John+cn=Doe,ou=People,dc=example,dc=com",
            "cn=doe+givenname=john,ou=people,dc=example,dc=com",
            "givenName=John+cn=Doe,ou=People,dc=example,dc=com" },
        { "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com",
            "givenname=john\\+cn=doe,ou=people,dc=example,dc=com",
            "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com" },
        { "cn=Doe\\, John,ou=People,dc=example,dc=com",
            "cn=doe\\, john,ou=people,dc=example,dc=com",
            "cn=Doe\\, John,ou=People,dc=example,dc=com" },
        { "UID=jsmith,DC=example,DC=net",
            "uid=jsmith,dc=example,dc=net",
            "UID=jsmith,DC=example,DC=net" },
        { "OU=Sales+CN=J. Smith,DC=example,DC=net",
            "cn=j. smith+ou=sales,dc=example,dc=net",
            "OU=Sales+CN=J. Smith,DC=example,DC=net" },
        { "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net",
            "cn=james \\\"jim\\\" smith\\, iii,dc=example,dc=net",
            "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net" },
        { "CN=John Smith\\2C III,DC=example,DC=net",
            "cn=john smith\\, iii,dc=example,dc=net",
            "CN=John Smith\\, III,DC=example,DC=net" },
        { "CN=\\23John Smith\\20,DC=example,DC=net",
            "cn=\\#john smith,dc=example,dc=net",
            "CN=\\#John Smith\\ ,DC=example,DC=net" },
        { "CN=Before\\0dAfter,DC=example,DC=net",
             //\0d is a hex representation of Carriage return. It is mapped
             //to a SPACE as defined in the MAP ( RFC 4518)
            "cn=before after,dc=example,dc=net",
            "CN=Before\\0dAfter,DC=example,DC=net" },
        { "1.3.6.1.4.1.1466.0=#04024869",
             //Unicode codepoints from 0000-0008 are mapped to nothing.
            "1.3.6.1.4.1.1466.0=hi",
            "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
        { "1.1.1=", "1.1.1=", "1.1.1=" },
        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107",
            "CN=Lu\u010di\u0107" },
        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius",
            "ou=\u55b6\u696d\u90e8,o=airius",
            "ou=\u55b6\u696d\u90e8,o=Airius" },
        { "photo=\\ john \\ ,dc=com", "photo=\\ john \\ ,dc=com",
      // raw dn, irreversible normalized string representation, toString representation
//        { "", "", "" },
//        { "   ", "", "" },
//        { "cn=", "cn=", "cn=" },
//        { "cn= ", "cn=", "cn=" },
//        { "cn =", "cn=", "cn=" },
//        { "cn = ", "cn=", "cn=" },
//        { "dc=com", "dc=com", "dc=com" },
//        { "dc=com+o=com", "dc=com+o=com", "dc=com+o=com" },
//        { "DC=COM", "dc=com", "DC=COM" },
//        { "dc = com", "dc=com", "dc=com" },
//        { " dc = com ", "dc=com", "dc=com" },
//        { "dc=example,dc=com", "dc=example,dc=com",
//            "dc=example,dc=com" },
//        { "dc=example, dc=com", "dc=example,dc=com",
//            "dc=example,dc=com" },
//        { "dc=example ,dc=com", "dc=example,dc=com",
//            "dc=example,dc=com" },
//        { "dc =example , dc  =   com", "dc=example,dc=com",
//            "dc=example,dc=com" },
//        { "givenName=John+cn=Doe,ou=People,dc=example,dc=com",
//            "cn=doe+givenname=john,ou=people,dc=example,dc=com",
//            "givenName=John+cn=Doe,ou=People,dc=example,dc=com" },
//        { "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com",
//            "givenname=john%2Bcn%3Ddoe,ou=people,dc=example,dc=com",
//            "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com" },
//        { "cn=Doe\\, John,ou=People,dc=example,dc=com",
//            "cn=doe%2C%20john,ou=people,dc=example,dc=com",
//            "cn=Doe\\, John,ou=People,dc=example,dc=com" },
//        { "UID=jsmith,DC=example,DC=net",
//            "uid=jsmith,dc=example,dc=net",
//            "UID=jsmith,DC=example,DC=net" },
//        { "OU=Sales+CN=J. Smith,DC=example,DC=net",
//            "cn=j.%20smith+ou=sales,dc=example,dc=net",
//            "OU=Sales+CN=J. Smith,DC=example,DC=net" },
//        { "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net",
//            "cn=james%20%22jim%22%20smith%2C%20iii,dc=example,dc=net",
//            "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net" },
//        { "CN=John Smith\\2C III,DC=example,DC=net",
//            "cn=john%20smith%2C%20iii,dc=example,dc=net",
//            "CN=John Smith\\, III,DC=example,DC=net" },
//        { "CN=\\23John Smith\\20,DC=example,DC=net",
//            "cn=%23john%20smith,dc=example,dc=net",
//            "CN=\\#John Smith\\ ,DC=example,DC=net" },
//        { "CN=Before\\0dAfter,DC=example,DC=net",
//             //\0d is a hex representation of Carriage return. It is mapped
//             //to a SPACE as defined in the MAP ( RFC 4518)
//            "cn=before%20after,dc=example,dc=net",
//            "CN=Before\\0dAfter,DC=example,DC=net" },
//        { "1.3.6.1.4.1.1466.0=#04024869",
//             //Unicode codepoints from 0000-0008 are mapped to nothing.
//            "1.3.6.1.4.1.1466.0=hi",
//            "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
//        { "1.1.1=", "1.1.1=", "1.1.1=" },
//        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=luc%CC%8Cic%CC%81",
//            "CN=Lu\u010di\u0107" },
//        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius",
//            "ou=%E5%96%B6%E6%A5%AD%E9%83%A8,o=airius",
//            "ou=\u55b6\u696d\u90e8,o=Airius" },
        { "photo=\\ john \\ ,dc=com", "photo=%20%6A%6F%68%6E%20%20,dc=com",
            "photo=\\ john \\ ,dc=com" },
        { "AB-global=", "ab-global=", "AB-global=" },
        { "OU= Sales + CN = J. Smith ,DC=example,DC=net",
            "cn=j. smith+ou=sales,dc=example,dc=net",
            "cn=j.%20smith+ou=sales,dc=example,dc=net",
            "OU=Sales+CN=J. Smith,DC=example,DC=net" },
        { "cn=John+a=", "a=+cn=john", "cn=John+a=" },
        { "OID.1.3.6.1.4.1.1466.0=#04024869",
@@ -123,7 +128,7 @@
            "1.3.6.1.4.1.1466.0=hi",
            "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
        { "O=\"Sue, Grabbit and Runn\",C=US",
            "o=sue\\, grabbit and runn,c=us",
            "o=sue%2C%20grabbit%20and%20runn,c=us",
            "O=Sue\\, Grabbit and Runn,C=US" }, };
  }
@@ -286,53 +291,68 @@
  /**
   * Tests the <CODE>decode</CODE> method which takes a String
   * Tests the <CODE>valueOf</CODE> method which takes a String
   * argument.
   *
   * @param rawDN
   *          Raw DN string representation.
   * @param normDN
   *          Normalized DN string representation.
   * @param stringDN
   *          String representation.
   * @param unused
   *          Unused argument.
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test(dataProvider = "testDNs")
  public void testDecodeString(String rawDN, String normDN,
      String stringDN) throws Exception {
  public void testValueOf(String rawDN, String normDN, String unused) throws Exception {
    DN dn = DN.valueOf(rawDN);
    StringBuilder buffer = new StringBuilder();
    buffer.append(normDN);
    Platform.normalize(buffer);
    assertEquals(dn.toNormalizedString(), buffer.toString());
    StringBuilder normalizedDnString = new StringBuilder(normDN);
    Platform.normalize(normalizedDnString);
    assertEquals(dn.toIrreversibleReadableString(), normalizedDnString.toString());
  }
  /**
   * Tests the <CODE>decode</CODE> method which takes a String
   * Tests the <CODE>decode</CODE> method which takes a ByteString
   * argument.
   *
   * @param rawDN
   *          Raw DN string representation.
   * @param normDN
   *          Normalized DN string representation.
   * @param unused
   *          Unused argument.
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test(dataProvider = "testDNs")
  public void testDecodeByteString(String rawDN, String normDN, String unused) throws Exception {
    DN dn = DN.decode(ByteString.valueOf(rawDN));
    StringBuilder normalizedDNString = new StringBuilder(normDN);
    Platform.normalize(normalizedDNString);
    assertEquals(dn.toIrreversibleReadableString(), normalizedDNString.toString());
  }
  /**
   * Test DN string decoder.
   *
   * @param rawDN
   *          Raw DN string representation.
   * @param unused
   *          Unused argument.
   * @param stringDN
   *          String representation.
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test(dataProvider = "testDNs")
  public void testDecodeOctetString(String rawDN, String normDN,
      String stringDN) throws Exception {
    ByteString octetString = ByteString.valueOf(rawDN);
    DN dn = DN.decode(octetString);
    StringBuilder buffer = new StringBuilder();
    buffer.append(normDN);
    Platform.normalize(buffer);
    assertEquals(dn.toNormalizedString(), buffer.toString());
  public void testToString(String rawDN, String unused, String stringDN) throws Exception {
    DN dn = DN.valueOf(rawDN);
    assertEquals(dn.toString(), stringDN);
  }
@@ -347,11 +367,10 @@
  public void testToNormalizedString() throws Exception {
    DN dn = DN.valueOf("dc=example,dc=com");
    StringBuilder buffer = new StringBuilder();
    dn.toNormalizedString(buffer);
    assertEquals(buffer.toString(), "dc=example,dc=com");
    assertEquals(dn.toNormalizedString(), "dc=example,dc=com");
    assertEquals(dn.toIrreversibleNormalizedByteString(),
        new ByteStringBuilder().append("dc=com").append(DN.NORMALIZED_RDN_SEPARATOR).append("dc=example")
        .toByteString());
    assertEquals(dn.toIrreversibleReadableString(), "dc=example,dc=com");
  }
@@ -436,7 +455,7 @@
    DN nullDN = DN.rootDN();
    assertTrue(nullDN.size() == 0);
    assertEquals(nullDN.toNormalizedString(), "");
    assertEquals(nullDN.toString(), "");
  }
@@ -615,7 +634,7 @@
    assertEquals(p, e);
    assertEquals(p.hashCode(), e.hashCode());
    assertEquals(p.toNormalizedString(), e.toNormalizedString());
    assertEquals(p.toIrreversibleReadableString(), e.toIrreversibleReadableString());
    assertEquals(p.toString(), e.toString());
    assertEquals(p.rdn(), RDN.decode("dc=bar"));
@@ -734,7 +753,7 @@
    // Shoudld throw.
    dn.getRDN(i);
    fail("Excepted exception for RDN index " + i + " in DN " + s);
    Assert.fail("Excepted exception for RDN index " + i + " in DN " + s);
  }
@@ -829,7 +848,7 @@
    assertEquals(c, e);
    assertEquals(c.hashCode(), e.hashCode());
    assertEquals(c.toNormalizedString(), e.toNormalizedString());
    assertEquals(c.toIrreversibleReadableString(), e.toIrreversibleReadableString());
    assertEquals(c.toString(), e.toString());
    assertEquals(c.rdn(), RDN.decode("dc=foo"));
@@ -1224,12 +1243,12 @@
    if (result == 0) {
      if (h1 != h2) {
        fail("Hash codes for <" + first + "> and <" + second
        Assert.fail("Hash codes for <" + first + "> and <" + second
            + "> should be the same.");
      }
    } else {
      if (h1 == h2) {
        fail("Hash codes for <" + first + "> and <" + second
        Assert.fail("Hash codes for <" + first + "> and <" + second
            + "> should be the same.");
      }
    }
@@ -1270,23 +1289,29 @@
  /**
   * Test DN string decoder.
   *
   * @param rawDN
   *          Raw DN string representation.
   * @param normDN
   *          Normalized DN string representation.
   * @param stringDN
   *          String representation.
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test(dataProvider = "testDNs")
  public void testToString(String rawDN, String normDN,
      String stringDN) throws Exception {
    DN dn = DN.valueOf(rawDN);
    assertEquals(dn.toString(), stringDN);
  @DataProvider
  public Object[][] renameData()
  {
    return new Object[][] {
        // DN to rename, from DN, to DN , expected DN after renaming
        { "dc=com", "dc=com", "dc=org", "dc=org" },
        { "dc=com2", "dc=com", "dc=org", "dc=com2" },
        { "dc=example1,dc=com", "dc=com", "dc=org", "dc=example1,dc=org"},
        { "dc=example1,dc=example2,dc=com", "dc=com", "dc=org", "dc=example1,dc=example2,dc=org"},
        { "dc=example1,dc=example2,dc=com", "dc=example2,dc=com", "dc=example2,dc=org",
            "dc=example1,dc=example2,dc=org"},
        { "dc=example1,dc=example2,dc=com", "dc=example2,dc=com", "dc=example3,dc=org",
            "dc=example1,dc=example3,dc=org"}
    };
  }
  @Test(dataProvider="renameData")
  public void testRename(String dnString, String fromDN, String toDN, String expectedDN) throws Exception
  {
    DN dn = DN.valueOf(dnString);
    DN renamed = dn.rename(DN.valueOf(fromDN), DN.valueOf(toDN));
    assertThat(renamed).isEqualTo(DN.valueOf(expectedDN));
  }
}
opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestRDN.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package org.opends.server.types;
@@ -195,50 +195,37 @@
  @DataProvider(name = "testRDNs")
  public Object[][] createData() {
    return new Object[][] {
        { "dc=hello world", "dc=hello world", "dc=hello world" },
        { "dc =hello world", "dc=hello world", "dc=hello world" },
        { "dc  =hello world", "dc=hello world", "dc=hello world" },
        { "dc= hello world", "dc=hello world", "dc=hello world" },
        { "dc=  hello world", "dc=hello world", "dc=hello world" },
        { "dc=hello world", "dc=hello%20world", "dc=hello world" },
        { "dc =hello world", "dc=hello%20world", "dc=hello world" },
        { "dc  =hello world", "dc=hello%20world", "dc=hello world" },
        { "dc= hello world", "dc=hello%20world", "dc=hello world" },
        { "dc=  hello world", "dc=hello%20world", "dc=hello world" },
        { "undefined=hello", "undefined=hello", "undefined=hello" },
        { "DC=HELLO WORLD", "dc=hello world", "DC=HELLO WORLD" },
        { "dc = hello    world", "dc=hello world",
            "dc=hello    world" },
        { "   dc = hello world   ", "dc=hello world",
            "dc=hello world" },
        { "givenName=John+cn=Doe", "cn=doe+givenname=john",
            "givenName=John+cn=Doe" },
        { "givenName=John\\+cn=Doe", "givenname=john\\+cn=doe",
            "givenName=John\\+cn=Doe" },
        { "cn=Doe\\, John", "cn=doe\\, john", "cn=Doe\\, John" },
        { "OU=Sales+CN=J. Smith", "cn=j. smith+ou=sales",
            "OU=Sales+CN=J. Smith" },
        { "CN=James \\\"Jim\\\" Smith\\, III",
            "cn=james \\\"jim\\\" smith\\, iii",
        { "DC=HELLO WORLD", "dc=hello%20world", "DC=HELLO WORLD" },
        { "dc = hello    world", "dc=hello%20world", "dc=hello    world" },
        { "   dc = hello world   ", "dc=hello%20world",  "dc=hello world" },
        { "givenName=John+cn=Doe", "cn=doe+givenname=john", "givenName=John+cn=Doe" },
        { "givenName=John\\+cn=Doe", "givenname=john%2Bcn%3Ddoe", "givenName=John\\+cn=Doe" },
        { "cn=Doe\\, John", "cn=doe%2C%20john", "cn=Doe\\, John" },
        { "OU=Sales+CN=J. Smith", "cn=j.%20smith+ou=sales","OU=Sales+CN=J. Smith" },
        { "CN=James \\\"Jim\\\" Smith\\, III", "cn=james%20%22jim%22%20smith%2C%20iii",
            "CN=James \\\"Jim\\\" Smith\\, III" },
            //\0d is a hex representation of Carriage return. It is mapped
             //to a SPACE as defined in the MAP ( RFC 4518)
        { "CN=Before\\0dAfter", "cn=before after",
            "CN=Before\\0dAfter" },
        { "CN=Before\\0dAfter", "cn=before%20after", "CN=Before\\0dAfter" },
        { "1.3.6.1.4.1.1466.0=#04024869",
            //Unicode codepoints from 0000-0008 are mapped to nothing.
            "1.3.6.1.4.1.1466.0=hi",
            "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107",
            "CN=Lu\u010di\u0107" },
        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8",
            "ou=\u55b6\u696d\u90e8",
            "ou=\u55b6\u696d\u90e8" },
        { "photo=\\ john \\ ", "photo=\\ john \\ ",
            "photo=\\ john \\ " },
            "1.3.6.1.4.1.1466.0=hi", "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=luc%CC%8Cic%CC%81", "CN=Lu\u010di\u0107" },
        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8", "ou=%E5%96%B6%E6%A5%AD%E9%83%A8", "ou=\u55b6\u696d\u90e8" },
        { "photo=\\ john \\ ", "photo=%20%6A%6F%68%6E%20%20", "photo=\\ john \\ " },
     //   { "AB-global=", "ab-global=", "AB-global=" },
        { "cn=John+a=", "a=+cn=john", "cn=John+a=" },
        { "OID.1.3.6.1.4.1.1466.0=#04024869",
            //Unicode codepoints from 0000-0008 are mapped to nothing.
            "1.3.6.1.4.1.1466.0=hi",
            "1.3.6.1.4.1.1466.0=\\04\\02Hi" },
        { "O=\"Sue, Grabbit and Runn\"", "o=sue\\, grabbit and runn",
            "O=Sue\\, Grabbit and Runn" }, };
        { "O=\"Sue, Grabbit and Runn\"", "o=sue%2C%20grabbit%20and%20runn", "O=Sue\\, Grabbit and Runn" }, };
  }
@@ -256,8 +243,7 @@
   *           If the test failed unexpectedly.
   */
  @Test(dataProvider = "testRDNs")
  public void testDecodeString(String rawRDN, String normRDN,
      String stringRDN) throws Exception {
  public void testNormalizeToReadableString(String rawRDN, String normRDN, String stringRDN) throws Exception {
    RDN rdn = RDN.decode(rawRDN);
    StringBuilder buffer = new StringBuilder();
    buffer.append(normRDN);