From 0d9afb0cda5c70acc780965dbe3687a254d23acf Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Thu, 25 Jun 2015 16:46:51 +0000
Subject: [PATCH] Fix 3.0 performance regression (CR-7367)

---
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java                              |   38 ++++++
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java                                        |   31 ++++
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java  |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java       |    4 
 opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties                                   |   13 +-
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java               |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java               |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java                                |    8 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SHA1PasswordStorageScheme.java             |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java                                        |    6 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RC4PasswordStorageScheme.java              |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java     |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java                                               |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java                                |    5 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/MD5PasswordStorageScheme.java              |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/AESPasswordStorageScheme.java              |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java           |    3 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java        |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java                                     |   43 ++++++-
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RandomPasswordGenerator.java               |    2 
 opendj-sdk/opendj-core/clirr-ignored-api-changes.xml                                                                  |    9 +
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java               |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/Base64PasswordStorageScheme.java           |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java   |   45 ++-----
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java     |    4 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/BlowfishPasswordStorageScheme.java         |    2 
 opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java                                       |   36 +++---
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CryptPasswordStorageScheme.java            |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java    |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java   |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/ClearPasswordStorageScheme.java            |    2 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java  |    2 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java     |    4 
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/TripleDESPasswordStorageScheme.java        |    2 
 35 files changed, 193 insertions(+), 110 deletions(-)

diff --git a/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml b/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
index 4f61db9..9640941 100644
--- a/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
+++ b/opendj-sdk/opendj-core/clirr-ignored-api-changes.xml
@@ -432,4 +432,13 @@
     <method>boolean startsWith(org.forgerock.opendj.ldap.ByteSequence)</method>
     <justification>Lack of startsWith() forced to re-implement it multiple times at different location</justification>
   </difference>
+	<difference>
+		<className>org/forgerock/opendj/ldap/ByteString</className>
+		<differenceType>7005</differenceType>
+		<method>org.forgerock.opendj.ldap.ByteString valueOf(java.lang.String)
+		</method>
+		<from>org.forgerock.opendj.ldap.ByteString valueOf(java.lang.String)</from>
+		<to>org.forgerock.opendj.ldap.ByteString valueOf(java.lang.CharSequence)</to>
+		<justification>Using CharSequence instead of String allows to reduce memory copy.</justification>
+	</difference>
 </differences>
diff --git a/opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java b/opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
index 6a095b8..1ba8bdc 100644
--- a/opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
+++ b/opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011-2014 ForgeRock AS
+ *      Portions copyright 2011-2015 ForgeRock AS
  */
 package com.forgerock.opendj.util;
 
@@ -1293,36 +1293,36 @@
 
     /**
      * Construct a byte array containing the UTF-8 encoding of the provided
-     * string. This is significantly faster than calling
+     * char sequence. This is significantly faster than calling
      * {@link String#getBytes(String)} for ASCII strings.
      *
      * @param s
-     *            The string to convert to a UTF-8 byte array.
+     *            The char sequence to convert to a UTF-8 byte array.
      * @return Returns a byte array containing the UTF-8 encoding of the
      *         provided string.
      */
-    public static byte[] getBytes(final String s) {
+    public static byte[] getBytes(final CharSequence s) {
         if (s == null) {
             return null;
         }
 
-        try {
-            char c;
-            final int length = s.length();
-            final byte[] returnArray = new byte[length];
-            for (int i = 0; i < length; i++) {
-                c = s.charAt(i);
-                returnArray[i] = (byte) (c & 0x0000007F);
-                if (c != returnArray[i]) {
-                    return s.getBytes("UTF-8");
+        char c;
+        final int length = s.length();
+        final byte[] returnArray = new byte[length];
+        for (int i = 0; i < length; i++) {
+            c = s.charAt(i);
+            returnArray[i] = (byte) (c & 0x0000007F);
+            if (c != returnArray[i]) {
+                try {
+                    return s.toString().getBytes("UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    // TODO: I18N
+                    throw new RuntimeException("Unable to encode UTF-8 string " + s, e);
                 }
             }
-
-            return returnArray;
-        } catch (final UnsupportedEncodingException e) {
-            // TODO: I18N
-            throw new RuntimeException("Unable to encode UTF-8 string " + s, e);
         }
+
+        return returnArray;
     }
 
     /**
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
index 761e67f..82ea182 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
@@ -383,7 +383,7 @@
                     reader.reset();
                     // Return what we have got here so far.
                     appendHexChars(reader, valueBuffer, hexBuffer);
-                    return ByteString.valueOf(valueBuffer.toString());
+                    return ByteString.valueOf(valueBuffer);
                 }
                 // It is definitely not a delimiter at this point.
                 appendHexChars(reader, valueBuffer, hexBuffer);
@@ -393,7 +393,7 @@
         }
 
         reader.reset();
-        return ByteString.valueOf(valueBuffer.toString());
+        return ByteString.valueOf(valueBuffer);
     }
 
     private static AttributeType readAttributeName(final SubstringReader reader, final Schema schema) {
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java
index 565c5d3..6762d6a 100755
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java
@@ -136,13 +136,13 @@
 
     /**
      * Returns a byte string containing the UTF-8 encoded bytes of the provided
-     * string.
+     * char sequence.
      *
      * @param s
-     *            The string to use.
+     *            The char sequence to use.
      * @return The byte string with the encoded bytes of the provided string.
      */
-    public static ByteString valueOf(final String s) {
+    public static ByteString valueOf(final CharSequence s) {
         if (s.length() == 0) {
             return EMPTY;
         }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
index 071d8ed..9f90b60 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
@@ -57,6 +57,6 @@
         normalizedValue.append('$');
         normalizedValue.append(authPWComponents[2]);
 
-        return ByteString.valueOf(normalizedValue.toString());
+        return ByteString.valueOf(normalizedValue);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
index 6c8169e..7fc85cd 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
@@ -851,7 +851,7 @@
             }
         }
 
-        return ByteString.valueOf(metaphone.toString());
+        return ByteString.valueOf(metaphone);
     }
 
     /**
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
index b5000c5..cfc547a 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
@@ -49,38 +49,21 @@
         super(EMR_OID_NAME);
     }
 
-    static String resolveNames(final Schema schema, final String oid) {
-        if (!StaticUtils.isDigit(oid.charAt(0))) {
-            // Do an best effort attempt to normalize names to OIDs.
-            String schemaName = null;
-            if (schema.hasAttributeType(oid)) {
-                schemaName = schema.getAttributeType(oid).getOID();
-            }
-            if (schemaName == null && schema.hasDITContentRule(oid)) {
-                schemaName = schema.getDITContentRule(oid).getStructuralClass().getOID();
-            }
-            if (schemaName == null && schema.hasSyntax(oid)) {
-                schemaName = schema.getSyntax(oid).getOID();
-            }
-            if (schemaName == null && schema.hasObjectClass(oid)) {
-                schemaName = schema.getObjectClass(oid).getOID();
-            }
-            if (schemaName == null && schema.hasMatchingRule(oid)) {
-                schemaName = schema.getMatchingRule(oid).getOID();
-            }
-            if (schemaName == null && schema.hasMatchingRuleUse(oid)) {
-                schemaName = schema.getMatchingRuleUse(oid).getMatchingRule().getOID();
-            }
-            if (schemaName == null && schema.hasNameForm(oid)) {
-                schemaName = schema.getNameForm(oid).getOID();
-            }
-
-            if (schemaName != null) {
-                return schemaName;
-            }
-            return StaticUtils.toLowerCase(oid);
+    static String resolveNames(final Schema schema, final String oidOrName) throws DecodeException {
+        if (StaticUtils.isDigit(oidOrName.charAt(0))) {
+            return oidOrName;
         }
-        return oid;
+        // Do a best effort attempt to normalize names to OIDs.
+        final String lowerCaseName = StaticUtils.toLowerCase(oidOrName.toLowerCase());
+        try {
+            final String oid = schema.getOIDForName(lowerCaseName);
+            if (oid != null) {
+                return oid;
+            }
+        } catch (UnknownSchemaElementException e) {
+            throw DecodeException.error(e.getMessageObject(), e);
+        }
+        return lowerCaseName;
     }
 
     @Override
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
index ed69340..b290b91 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -83,6 +83,8 @@
 
         Syntax getDefaultSyntax();
 
+        String getOIDForName(String lowerCaseName);
+
         AttributeType getAttributeType(Schema schema, String name);
 
         Collection<AttributeType> getAttributeTypes();
@@ -193,6 +195,11 @@
         }
 
         @Override
+        public String getOIDForName(final String lowerCaseName) {
+            return strictImpl.getOIDForName(lowerCaseName);
+        }
+
+        @Override
         public AttributeType getAttributeType(final Schema schema, final String name) {
             final AttributeType type = strictImpl.getAttributeType0(name);
             return type != null ? type : new AttributeType(schema, name);
@@ -409,6 +416,7 @@
         private final Map<String, ObjectClass> numericOID2ObjectClasses;
         private final Map<String, Syntax> numericOID2Syntaxes;
         private final Map<String, List<NameForm>> objectClass2NameForms;
+        private final Map<String, String> name2OIDs;
         private final List<LocalizableMessage> warnings;
         private final String schemaName;
         private final SchemaOptions options;
@@ -438,6 +446,7 @@
                 final Map<String, List<DITStructureRule>> name2StructureRules,
                 final Map<String, List<NameForm>> objectClass2NameForms,
                 final Map<String, List<DITStructureRule>> nameForm2StructureRules,
+                final Map<String, String> name2OIDs,
                 final List<LocalizableMessage> warnings) {
             this.schemaName = schemaName;
             this.options = SchemaOptions.unmodifiable(options);
@@ -460,6 +469,7 @@
             this.name2StructureRules = Collections.unmodifiableMap(name2StructureRules);
             this.objectClass2NameForms = Collections.unmodifiableMap(objectClass2NameForms);
             this.nameForm2StructureRules = Collections.unmodifiableMap(nameForm2StructureRules);
+            this.name2OIDs = Collections.unmodifiableMap(name2OIDs);
             this.warnings = Collections.unmodifiableList(warnings);
             this.strictSchema = new Schema(this);
             this.nonStrictSchema = new Schema(new NonStrictImpl(this));
@@ -491,6 +501,16 @@
         }
 
         @Override
+        public String getOIDForName(String lowerCaseName) {
+            final String oid = name2OIDs.get(lowerCaseName);
+            // == is correct, AMBIGUOUS_OID is singleton to mark an entry ambiguous
+            if (oid == SchemaBuilder.AMBIGUOUS_OID) {
+                throw new UnknownSchemaElementException(WARN_NAME_AMBIGUOUS.get(lowerCaseName));
+            }
+            return oid;
+        }
+
+        @Override
         public AttributeType getAttributeType(final Schema schema, final String name) {
             final AttributeType type = getAttributeType0(name);
             if (type != null) {
@@ -531,7 +551,7 @@
                 if (rules.size() == 1) {
                     return rules.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_DCR_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_DCR_AMBIGUOUS.get(name));
             }
             throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN.get(name));
         }
@@ -595,7 +615,7 @@
                 if (rules.size() == 1) {
                     return rules.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_MR_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_MR_AMBIGUOUS.get(name));
             }
             throw new UnknownSchemaElementException(WARN_MR_UNKNOWN.get(name));
         }
@@ -631,7 +651,7 @@
                 if (uses.size() == 1) {
                     return uses.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_MRU_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_MRU_AMBIGUOUS.get(name));
             }
             throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN.get(name));
         }
@@ -662,7 +682,7 @@
                 if (forms.size() == 1) {
                     return forms.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_NAMEFORM_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_NAMEFORM_AMBIGUOUS.get(name));
             }
             throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN.get(name));
         }
@@ -701,7 +721,7 @@
                 if (classes.size() == 1) {
                     return classes.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_OBJECTCLASS_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_OBJECTCLASS_AMBIGUOUS.get(name));
             }
             throw new UnknownSchemaElementException(WARN_OBJECTCLASS_UNKNOWN.get(name));
         }
@@ -826,7 +846,7 @@
                 if (attributes.size() == 1) {
                     return attributes.get(0);
                 }
-                throw new UnknownSchemaElementException(WARN_ATTR_TYPE_AMBIGIOUS.get(name));
+                throw new UnknownSchemaElementException(WARN_ATTR_TYPE_AMBIGUOUS.get(name));
             }
             return null;
         }
@@ -1088,6 +1108,17 @@
     }
 
     /**
+     * Return the numerical OID matching the lowerCaseName.
+     * @param lowerCaseName The lower case name
+     * @return OID matching the name or null if name doesn't match to an OID
+     * @throws UnknownSchemaElementException if multiple OID are matching
+     * lowerCaseName
+     */
+    String getOIDForName(String lowerCaseName) {
+        return impl.getOIDForName(lowerCaseName);
+    }
+
+    /**
      * Returns the attribute type with the specified name or numeric OID.
      * <p>
      * If the requested attribute type is not registered in this schema and this
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
index 7e93d70..2d5ff11 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -85,6 +85,9 @@
  */
 public final class SchemaBuilder {
 
+    /** Constant used for name to oid mapping when one name actually maps to multiple numerical OID. */
+    public static final String AMBIGUOUS_OID = "<ambiguous-oid>";
+
     private static final String ATTR_SUBSCHEMA_SUBENTRY = "subschemaSubentry";
 
     private static final String[] SUBSCHEMA_ATTRS = { ATTR_LDAP_SYNTAXES,
@@ -151,6 +154,7 @@
     private Map<String, ObjectClass> numericOID2ObjectClasses;
     private Map<String, Syntax> numericOID2Syntaxes;
     private Map<String, List<NameForm>> objectClass2NameForms;
+    private Map<String, String> name2OIDs;
     private String schemaName;
     private List<LocalizableMessage> warnings;
     private SchemaOptions options;
@@ -2137,7 +2141,7 @@
                         numericOID2ContentRules, id2StructureRules, name2MatchingRules,
                         name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
                         name2NameForms, name2ContentRules, name2StructureRules,
-                        objectClass2NameForms, nameForm2StructureRules, warnings).asStrictSchema();
+                        objectClass2NameForms, nameForm2StructureRules, name2OIDs, warnings).asStrictSchema();
         validate(schema);
 
         // Re-init this builder so that it can continue to be used afterwards.
@@ -2146,6 +2150,12 @@
         return schema;
     }
 
+    private void registerNameToOIDMapping(String name, String anOID) {
+        if (name2OIDs.put(name, anOID) != null) {
+            name2OIDs.put(name, AMBIGUOUS_OID);
+        }
+    }
+
     SchemaBuilder addAttributeType(final AttributeType attribute, final boolean overwrite) {
         AttributeType conflictingAttribute;
         if (numericOID2AttributeTypes.containsKey(attribute.getOID())) {
@@ -2421,6 +2431,7 @@
             }
             removeSyntax(conflictingSyntax);
         }
+
         numericOID2Syntaxes.put(syntax.getOID(), syntax);
         return this;
     }
@@ -2449,6 +2460,7 @@
 
             objectClass2NameForms = new HashMap<>();
             nameForm2StructureRules = new HashMap<>();
+            name2OIDs = new HashMap<>();
             warnings = new LinkedList<>();
         }
 
@@ -2605,6 +2617,7 @@
                 new Syntax[numericOID2Syntaxes.values().size()])) {
             try {
                 syntax.validate(schema, warnings);
+                registerNameToOIDMapping(syntax.getName(), syntax.getOID());
             } catch (final SchemaException e) {
                 removeSyntax(syntax);
                 warnings.add(ERR_SYNTAX_VALIDATION_FAIL
@@ -2616,6 +2629,9 @@
                 new MatchingRule[numericOID2MatchingRules.values().size()])) {
             try {
                 rule.validate(schema, warnings);
+                for (final String name : rule.getNames()) {
+                    registerNameToOIDMapping(StaticUtils.toLowerCase(name), rule.getOID());
+                }
             } catch (final SchemaException e) {
                 removeMatchingRule(rule);
                 warnings.add(ERR_MR_VALIDATION_FAIL.get(rule.toString(), e.getMessageObject()));
@@ -2633,6 +2649,12 @@
             removeAttributeType(attributeType);
         }
 
+        for (final AttributeType attributeType : numericOID2AttributeTypes.values()) {
+            for (final String name : attributeType.getNames()) {
+                registerNameToOIDMapping(StaticUtils.toLowerCase(name), attributeType.getOID());
+            }
+        }
+
         // Object classes need special processing because they have hierarchical
         // dependencies.
         final List<ObjectClass> invalidObjectClasses = new LinkedList<>();
@@ -2644,10 +2666,18 @@
             removeObjectClass(objectClass);
         }
 
+        for (final ObjectClass objectClass : numericOID2ObjectClasses.values()) {
+            for (final String name : objectClass.getNames()) {
+                registerNameToOIDMapping(StaticUtils.toLowerCase(name), objectClass.getOID());
+            }
+        }
         for (final MatchingRuleUse use : numericOID2MatchingRuleUses.values().toArray(
                 new MatchingRuleUse[numericOID2MatchingRuleUses.values().size()])) {
             try {
                 use.validate(schema, warnings);
+                for (final String name : use.getNames()) {
+                    registerNameToOIDMapping(StaticUtils.toLowerCase(name), use.getMatchingRuleOID());
+                }
             } catch (final SchemaException e) {
                 removeMatchingRuleUse(use);
                 warnings.add(ERR_MRU_VALIDATION_FAIL.get(use.toString(), e.getMessageObject()));
@@ -2671,6 +2701,9 @@
                 } else {
                     forms.add(form);
                 }
+                for (final String name : form.getNames()) {
+                    registerNameToOIDMapping(StaticUtils.toLowerCase(name), form.getOID());
+                }
             } catch (final SchemaException e) {
                 removeNameForm(form);
                 warnings.add(ERR_NAMEFORM_VALIDATION_FAIL
@@ -2682,6 +2715,9 @@
                 new DITContentRule[numericOID2ContentRules.values().size()])) {
             try {
                 rule.validate(schema, warnings);
+                for (final String name : rule.getNames()) {
+                    registerNameToOIDMapping(StaticUtils.toLowerCase(name), rule.getStructuralClassOID());
+                }
             } catch (final SchemaException e) {
                 removeDITContentRule(rule);
                 warnings.add(ERR_DCR_VALIDATION_FAIL.get(rule.toString(), e.getMessageObject()));
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java
index 7158c2b..8c5fdc0 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java
@@ -702,7 +702,7 @@
             return singleSpaceOrEmpty(value);
         }
         trimUnnecessarySpacesInStringList(buffer);
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 
     private static void trimUnnecessarySpacesInStringList(StringBuilder buffer) {
@@ -729,7 +729,7 @@
         if (buffer.length() == 0) {
             return singleSpaceOrEmpty(value);
         }
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 
     static ByteString normalizeIA5StringAttributeValue(final ByteSequence value, boolean trim, boolean foldCase)
@@ -741,7 +741,7 @@
             return singleSpaceOrEmpty(value);
         }
         throwIfIA5IllegalCharacter(buffer, value);
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 
     static void throwDecodeException(LocalizedLogger logger, LocalizableMessage message) throws DecodeException {
@@ -780,7 +780,7 @@
         if (buffer.length() == 0) {
             return ByteString.empty();
         }
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
index 40b17c4..d3992dd 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
@@ -59,6 +59,6 @@
             }
         }
 
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
index b72de8f..5c8ac9a 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
@@ -59,6 +59,6 @@
             }
         }
 
-        return ByteString.valueOf(buffer.toString());
+        return ByteString.valueOf(buffer);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
index 727eb00..9bb56d7 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
@@ -122,6 +122,6 @@
             }
         }
 
-        return ByteString.valueOf(builder.toString());
+        return ByteString.valueOf(builder);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
index 427b5de..8532b34 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
@@ -123,6 +123,6 @@
             }
         }
 
-        return ByteString.valueOf(builder.toString());
+        return ByteString.valueOf(builder);
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
index 1922c45..6753120 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
@@ -64,7 +64,7 @@
             final ByteSequence seq2 = value.subSequence(closingBracePos + 1, value.length());
             StaticUtils.toLowerCase(seq1, builder);
             builder.append(seq2);
-            return ByteString.valueOf(builder.toString());
+            return ByteString.valueOf(builder);
         } else {
             return value.toByteString();
         }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
index f827783..cf73a9c 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009 Sun Microsystems, Inc.
- *      Portions copyright 2011-2013 ForgeRock AS
+ *      Portions copyright 2011-2015 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldif;
@@ -300,8 +300,7 @@
 
     final void writeKeyAndValue(final CharSequence key, final CharSequence value)
             throws IOException {
-        // FIXME: We should optimize this at some point.
-        writeKeyAndValue(key, ByteString.valueOf(value.toString()));
+        writeKeyAndValue(key, ByteString.valueOf(value));
     }
 
     final void writeLine(final CharSequence line) throws IOException {
diff --git a/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index b7a680f..01b41a8 100755
--- a/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -441,17 +441,18 @@
   OID "%s" exists in the schema
 WARN_SYNTAX_UNKNOWN=No syntax with OID "%s" exists in the \
   schema
-WARN_ATTR_TYPE_AMBIGIOUS=Multiple attribute types with name %s \
+WARN_NAME_AMBIGUOUS=Multiple OID with name %s exists in the schema
+WARN_ATTR_TYPE_AMBIGUOUS=Multiple attribute types with name %s \
   exists in the schema
-WARN_OBJECTCLASS_AMBIGIOUS=Multiple object classes with name \
+WARN_OBJECTCLASS_AMBIGUOUS=Multiple object classes with name \
   %s exists in the schema
-WARN_MR_AMBIGIOUS=Multiple matching rules with name %s \
+WARN_MR_AMBIGUOUS=Multiple matching rules with name %s \
   exists in the schema
-WARN_MRU_AMBIGIOUS=Multiple matching rule uses with name %s \
+WARN_MRU_AMBIGUOUS=Multiple matching rule uses with name %s \
   exists in the schema
-WARN_DCR_AMBIGIOUS=Multiple DIT content rules with name %s \
+WARN_DCR_AMBIGUOUS=Multiple DIT content rules with name %s \
   exists in the schema
-WARN_NAMEFORM_AMBIGIOUS=Multiple name forms with name %s \
+WARN_NAMEFORM_AMBIGUOUS=Multiple name forms with name %s \
   exists in the schema
 WARN_ATTR_SYNTAX_SUBSTRING_NO_WILDCARDS=The provided \
  value "%s" could not be parsed as a substring assertion because it does not \
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
index 581f776..654f7a3 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
@@ -1245,7 +1245,7 @@
         }
       }
 
-      attributeValues.add(ByteString.valueOf(valueString.toString()));
+      attributeValues.add(ByteString.valueOf(valueString));
       return pos;
     }
 
@@ -1264,7 +1264,7 @@
       else if (c == '*')
       {
         escaped = false;
-        attributeValues.add(ByteString.valueOf(valueString.toString()));
+        attributeValues.add(ByteString.valueOf(valueString));
       }
       else
       {
@@ -1362,7 +1362,7 @@
             throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX,
                                          message);
           }
-          attributeValues.add(ByteString.valueOf(valueString.toString()));
+          attributeValues.add(ByteString.valueOf(valueString));
           valueString = new StringBuilder();
           hexChars = new StringBuilder();
         }
@@ -1395,7 +1395,7 @@
       }
 
 
-      attributeValues.add(ByteString.valueOf(valueString.toString()));
+      attributeValues.add(ByteString.valueOf(valueString));
       return pos;
     }
   }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/AESPasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/AESPasswordStorageScheme.java
index f808308..31af84b 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/AESPasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/AESPasswordStorageScheme.java
@@ -160,7 +160,7 @@
         Arrays.fill(plaintextBytes, (byte) 0);
     }
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
   /** {@inheritDoc} */
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/Base64PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/Base64PasswordStorageScheme.java
index 62a4b8a..b11f5cd 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/Base64PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/Base64PasswordStorageScheme.java
@@ -110,7 +110,7 @@
     buffer.append('}');
     buffer.append(Base64.encode(plaintext));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/BlowfishPasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
index df059bb..b571a1f 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
@@ -169,7 +169,7 @@
         Arrays.fill(plaintextBytes, (byte) 0);
     }
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
index f3cf6af..a033c1a 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
@@ -188,8 +188,7 @@
       }
       challengeString.append('>');
 
-      ByteString challenge =
-          ByteString.valueOf(challengeString.toString());
+      final ByteString challenge = ByteString.valueOf(challengeString);
       clientConnection.setSASLAuthStateInfo(challenge);
       bindOperation.setServerSASLCredentials(challenge);
       bindOperation.setResultCode(ResultCode.SASL_BIND_IN_PROGRESS);
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/ClearPasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/ClearPasswordStorageScheme.java
index c0ac257..b3616f5 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/ClearPasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/ClearPasswordStorageScheme.java
@@ -103,7 +103,7 @@
     buffer.append('}');
     buffer.append(plaintext.toString());
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CryptPasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CryptPasswordStorageScheme.java
index f03638e..a82aee4 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CryptPasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/CryptPasswordStorageScheme.java
@@ -272,7 +272,7 @@
 
     buffer.append(encodePassword(plaintext));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
   /**
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/MD5PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/MD5PasswordStorageScheme.java
index 9203a2a..fd511d9 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/MD5PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/MD5PasswordStorageScheme.java
@@ -202,7 +202,7 @@
     buffer.append(Base64.encode(digestBytes));
 
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RC4PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RC4PasswordStorageScheme.java
index 8f3ef2c..b05a21e 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RC4PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RC4PasswordStorageScheme.java
@@ -168,7 +168,7 @@
         Arrays.fill(plaintextBytes, (byte) 0);
     }
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RandomPasswordGenerator.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RandomPasswordGenerator.java
index aef6bb3..8075ad2 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RandomPasswordGenerator.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/RandomPasswordGenerator.java
@@ -253,7 +253,7 @@
       }
     }
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SHA1PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SHA1PasswordStorageScheme.java
index 6832ec4..e211e02 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SHA1PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SHA1PasswordStorageScheme.java
@@ -200,7 +200,7 @@
 
     buffer.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
index 0398cbc..22f4931 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
@@ -246,7 +246,7 @@
                      NUM_SALT_BYTES);
     buffer.append(Base64.encode(hashPlusSalt));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
@@ -383,7 +383,7 @@
     authPWValue.append('$');
     authPWValue.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(authPWValue.toString());
+    return ByteString.valueOf(authPWValue);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
index 8f6f4d5..0768f6c 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
@@ -245,7 +245,7 @@
                      NUM_SALT_BYTES);
     buffer.append(Base64.encode(hashPlusSalt));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
@@ -382,7 +382,7 @@
     authPWValue.append('$');
     authPWValue.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(authPWValue.toString());
+    return ByteString.valueOf(authPWValue);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
index af39d72..698a070 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
@@ -250,7 +250,7 @@
                      NUM_SALT_BYTES);
     buffer.append(Base64.encode(hashPlusSalt));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
@@ -389,7 +389,7 @@
     authPWValue.append('$');
     authPWValue.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(authPWValue.toString());
+    return ByteString.valueOf(authPWValue);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
index e3f4b78..5dc812c 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
@@ -251,7 +251,7 @@
                      NUM_SALT_BYTES);
     buffer.append(Base64.encode(hashPlusSalt));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
@@ -390,7 +390,7 @@
     authPWValue.append('$');
     authPWValue.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(authPWValue.toString());
+    return ByteString.valueOf(authPWValue);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
index 032f07e..7a57732 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
@@ -250,7 +250,7 @@
                      NUM_SALT_BYTES);
     buffer.append(Base64.encode(hashPlusSalt));
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
@@ -389,7 +389,7 @@
     authPWValue.append('$');
     authPWValue.append(Base64.encode(digestBytes));
 
-    return ByteString.valueOf(authPWValue.toString());
+    return ByteString.valueOf(authPWValue);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/TripleDESPasswordStorageScheme.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
index 22b30dd..d0ad0f9 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
@@ -169,7 +169,7 @@
         Arrays.fill(plaintextBytes, (byte) 0);
     }
 
-    return ByteString.valueOf(buffer.toString());
+    return ByteString.valueOf(buffer);
   }
 
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
index f760861..2b5447d 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
@@ -71,6 +71,8 @@
   /** The set of user-provided names for the attributes in this RDN. */
   private String[] attributeNames;
 
+  /** Representation of the normalized form of this RDN. */
+  private ByteString normalizedRDN;
 
 
   /**
@@ -1009,8 +1011,13 @@
     return buffer.toString();
   }
 
-  private ByteString toNormalizedByteString() {
-    return toNormalizedByteString(new ByteStringBuilder()).toByteString();
+  private ByteString toNormalizedByteString()
+  {
+    if (normalizedRDN == null)
+    {
+      computeNormalizedByteString(new ByteStringBuilder());
+    }
+    return normalizedRDN;
   }
 
   /**
@@ -1024,7 +1031,19 @@
    *           Builder to add this representation to.
    * @return the builder
    */
-  public ByteStringBuilder toNormalizedByteString(ByteStringBuilder builder) {
+  public ByteStringBuilder toNormalizedByteString(ByteStringBuilder builder)
+  {
+    if (normalizedRDN != null)
+    {
+      return builder.append(normalizedRDN);
+    }
+    return computeNormalizedByteString(builder);
+  }
+
+  private ByteStringBuilder computeNormalizedByteString(ByteStringBuilder builder)
+  {
+    final int startPos = builder.length();
+
     if (attributeNames.length == 1)
     {
       normalizeAVAToByteString(0, builder);
@@ -1048,6 +1067,12 @@
         builder.append(iterator.next());
       }
     }
+
+    if (normalizedRDN == null)
+    {
+      normalizedRDN = builder.subSequence(startPos, builder.length()).toByteString();
+    }
+
     return builder;
   }
 

--
Gitblit v1.10.0