From 60f3502563cd2c71a751b74f0b34bfe2f5d17330 Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Thu, 08 Nov 2012 15:40:09 +0000
Subject: [PATCH] Fix OPENDJ-619 : Reduce the memory utilization of LDIF.diff(EntryReader, EntryReader) in the SDK
---
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java | 136 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 136 insertions(+), 0 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
index e2ed752..a32ce02 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
@@ -27,19 +27,24 @@
package org.forgerock.opendj.ldap;
+import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_DN_TYPE_NOT_FOUND;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.TreeSet;
import java.util.WeakHashMap;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
+import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.schema.Syntax;
import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException;
+import com.forgerock.opendj.util.StaticUtils;
import com.forgerock.opendj.util.SubstringReader;
import com.forgerock.opendj.util.Validator;
@@ -799,4 +804,135 @@
}
return stringValue;
}
+
+ /**
+ * Returns the normalized string representation of a DN.
+ *
+ * @return The normalized string representation of the provided DN.
+ */
+ public String toNormalizedString() {
+ final StringBuilder builder = new StringBuilder(this.size());
+ if (rdn() == null) {
+ return builder.toString();
+ }
+
+ int i = this.size() - 1;
+ normalizeRDN(builder, parent(i).rdn());
+ for (i--; i >= 0; i--) {
+ final RDN rdn = parent(i).rdn();
+ // Only add a separator if the RDN is not RDN.maxValue().
+ if (rdn.size() != 0) {
+ builder.append('\u0000');
+ }
+ normalizeRDN(builder, rdn);
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Returns the normalized string representation of a RDN.
+ *
+ * @param builder
+ * The StringBuilder to use to construct the normalized string.
+ * @param rdn
+ * The RDN.
+ * @return The normalized string representation of the provided RDN.
+ */
+ private static StringBuilder normalizeRDN(final StringBuilder builder, final RDN rdn) {
+ final int sz = rdn.size();
+ switch (sz) {
+ case 0:
+ // Handle RDN.maxValue().
+ builder.append('\u0001');
+ break;
+ case 1:
+ normalizeAVA(builder, rdn.getFirstAVA());
+ break;
+ default:
+ // Need to sort the AVAs before comparing.
+ TreeSet<AVA> a = new TreeSet<AVA>();
+ for (AVA ava : rdn) {
+ a.add(ava);
+ }
+ Iterator<AVA> i = a.iterator();
+ // Normalize the first AVA.
+ normalizeAVA(builder, i.next());
+ while (i.hasNext()) {
+ builder.append('\u0001');
+ normalizeAVA(builder, i.next());
+ }
+ break;
+ }
+ return builder;
+ }
+
+ /**
+ * Returns the normalized string representation of an AVA.
+ *
+ * @param builder
+ * The StringBuilder to use to construct the normalized string.
+ * @param ava
+ * The AVA.
+ * @return The normalized string representation of the provided AVA.
+ */
+ private static StringBuilder normalizeAVA(final StringBuilder builder, final AVA ava) {
+ ByteString value = ava.getAttributeValue();
+ final MatchingRule matchingRule = ava.getAttributeType().getEqualityMatchingRule();
+ if (matchingRule != null) {
+ try {
+ value = matchingRule.normalizeAttributeValue(ava.getAttributeValue());
+ } catch (final DecodeException de) {
+ // Ignore - we'll drop back to the user provided value.
+ }
+ }
+
+ if (!ava.getAttributeType().getNames().iterator().hasNext()) {
+ builder.append(ava.getAttributeType().getOID());
+ builder.append("=#");
+ StaticUtils.toHex(value, builder);
+ } else {
+ final String name = ava.getAttributeType().getNameOrOID();
+ // Normalizing.
+ StaticUtils.toLowerCase(name, builder);
+
+ builder.append("=");
+
+ final Syntax syntax = ava.getAttributeType().getSyntax();
+ if (!syntax.isHumanReadable()) {
+ builder.append("#");
+ StaticUtils.toHex(value, builder);
+ } else {
+ final String str = value.toString();
+ if (str.length() == 0) {
+ return builder;
+ }
+ char c = str.charAt(0);
+ int startPos = 0;
+ if ((c == ' ') || (c == '#')) {
+ builder.append('\\');
+ builder.append(c);
+ startPos = 1;
+ }
+ final int length = str.length();
+ for (int si = startPos; si < length; si++) {
+ c = str.charAt(si);
+ if (c < ' ') {
+ for (final byte b : getBytes(String.valueOf(c))) {
+ builder.append('\\');
+ builder.append(StaticUtils.byteToLowerHex(b));
+ }
+ } else {
+ if ((c == ' ' && si == length - 1)
+ || (c == '"' || c == '+' || c == ',' || c == ';' || c == '<'
+ || c == '=' || c == '>' || c == '\\' || c == '\u0000')) {
+ builder.append('\\');
+ }
+ builder.append(c);
+ }
+ }
+ }
+ }
+ return builder;
+ }
+
}
--
Gitblit v1.10.0