From b82be51745e0db2395e3ee3c08e28ec3da869e29 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 16 Mar 2015 12:52:54 +0000
Subject: [PATCH] OPENDJ-1585 Update DN normalization in SDK to align with server
---
opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java | 80 ++++++++-------
opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java | 6
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java | 2
opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java | 2
opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java | 23 ++--
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java | 2
opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java | 133 +++++++++-----------------
opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java | 2
8 files changed, 106 insertions(+), 144 deletions(-)
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
index 6b84fbf..761e67f 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
@@ -799,7 +799,7 @@
* @param builder
* The builder to use to construct the normalized byte string.
* @return The normalized byte string representation.
- * @see DN#toIrreversibleNormalizedByteString()
+ * @see DN#toNormalizedByteString()
*/
ByteStringBuilder toNormalizedByteString(final ByteStringBuilder builder) {
builder.append(toLowerCase(attributeType.getNameOrOID()));
@@ -819,9 +819,9 @@
* @param builder
* The builder to use to construct the normalized string.
* @return The normalized readable string representation.
- * @see DN#toIrreversibleReadableString()
+ * @see DN#toNormalizedUrlSafeString()
*/
- StringBuilder toNormalizedReadableString(final StringBuilder builder) {
+ StringBuilder toNormalizedUrlSafe(final StringBuilder builder) {
builder.append(toLowerCase(attributeType.getNameOrOID()));
builder.append('=');
final ByteString value = getEqualityNormalizedValue();
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java
index 622967f..b19c56b 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java
@@ -258,7 +258,8 @@
/**
* Compares the provided DN values to determine their relative order in a
- * sorted list.
+ * sorted list. The order is the natural order as defined by the
+ * {@code toNormalizedByteString()} method.
*
* @param dn1
* The first DN to be compared. It must not be {@code null}.
@@ -270,42 +271,7 @@
* values can be considered equal.
*/
private static int compareTo(final DN dn1, final DN dn2) {
- // Quickly check if we are comparing against root dse.
- if (dn1.isRootDN()) {
- if (dn2.isRootDN()) {
- // both are equal.
- return 0;
- }
- // dn1 comes before dn2.
- return -1;
- }
-
- if (dn2.isRootDN()) {
- // dn1 comes after dn2.
- return 1;
- }
-
- int dn1Size = dn1.size - 1;
- int dn2Size = dn2.size - 1;
- while (dn1Size >= 0 && dn2Size >= 0) {
- final DN dn1Parent = dn1.parent(dn1Size--);
- final DN dn2Parent = dn2.parent(dn2Size--);
- final int result = dn1Parent.rdn.compareTo(dn2Parent.rdn);
- if (result > 0) {
- return 1;
- } else if (result < 0) {
- return -1;
- }
- }
-
- // What do we have here?
- if (dn1Size > dn2Size) {
- return 1;
- } else if (dn1Size < dn2Size) {
- return -1;
- }
-
- return 0;
+ return dn1.toNormalizedByteString().compareTo(dn2.toNormalizedByteString());
}
/** Decodes a DN using the provided reader and schema. */
@@ -370,6 +336,12 @@
private final int size;
/**
+ * The normalized byte string representation of this DN, which is not
+ * a valid DN and is not reversible to a valid DN.
+ */
+ private ByteString normalizedDN;
+
+ /**
* We need to store the original string value if provided in order to
* preserve the original whitespace.
*/
@@ -497,29 +469,18 @@
public boolean equals(final Object obj) {
if (this == obj) {
return true;
- } else if (obj instanceof DN) {
- DN other = (DN) obj;
- if (size == other.size()) {
- if (size == 0) {
- return true;
- }
-
- if (rdn.equals(other.rdn)) {
- return parent.equals(other.parent);
- }
- }
}
-
+ if (obj instanceof DN) {
+ DN otherDN = (DN) obj;
+ return toNormalizedByteString().equals(otherDN.toNormalizedByteString());
+ }
return false;
}
/** {@inheritDoc} */
@Override
public int hashCode() {
- if (size == 0) {
- return 0;
- }
- return 31 * parent.hashCode() + rdn.hashCode();
+ return toNormalizedByteString().hashCode();
}
/**
@@ -920,62 +881,60 @@
}
/**
- * 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.
+ * Retrieves a normalized byte string representation of this DN.
* <p>
- * 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.
+ * This representation is suitable for equality and comparisons, and
+ * for providing a natural hierarchical ordering.
+ * However, it is not a valid DN and can't be reverted to a valid DN.
+ * You should consider using a {@code CompactDn} as an alternative.
*
- * @return The normalized byte string representation of the provided DN, not
- * usable as a valid DN
+ * @return The normalized string representation of this DN.
*/
- public ByteString toIrreversibleNormalizedByteString() {
- if (rdn() == null) {
- return ByteString.empty();
- }
-
- final ByteStringBuilder builder = new ByteStringBuilder();
- int i = size() - 1;
- parent(i).rdn().toNormalizedByteString(builder);
- 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(DN.NORMALIZED_RDN_SEPARATOR);
+ public ByteString toNormalizedByteString() {
+ if (normalizedDN == null) {
+ if (rdn() == null) {
+ normalizedDN = ByteString.empty();
+ } else {
+ final ByteStringBuilder builder = new ByteStringBuilder();
+ int i = size() - 1;
+ parent(i).rdn().toNormalizedByteString(builder);
+ 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(DN.NORMALIZED_RDN_SEPARATOR);
+ }
+ rdn.toNormalizedByteString(builder);
+ }
+ normalizedDN = builder.toByteString();
}
- rdn.toNormalizedByteString(builder);
}
- return builder.toByteString();
+ return normalizedDN;
}
/**
- * Returns the irreversible readable string representation of a DN, suitable
- * for equality and usage as a name in file system or URL, but not usable as
- * a valid DN nor reversible to a valid DN.
+ * Retrieves a normalized string representation of this DN.
* <p>
- * This representation should be used only when a string representation is
- * needed and when no reversibility to a valid DN is needed.
+ * This representation is safe to use in an URL or in a file name.
+ * However, it is not a valid DN and can't be reverted to a valid DN.
*
- * @return The readable string representation of the provided DN,
- * not usable as a valid DN
+ * @return The normalized string representation of this DN.
*/
- public String toIrreversibleReadableString() {
+ public String toNormalizedUrlSafeString() {
if (rdn() == null) {
return "";
}
final StringBuilder builder = new StringBuilder();
int i = size() - 1;
- parent(i).rdn().toNormalizedReadableString(builder);
+ parent(i).rdn().toNormalizedUrlSafeString(builder);
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(',');
}
- rdn.toNormalizedReadableString(builder);
+ rdn.toNormalizedUrlSafeString(builder);
}
return builder.toString();
}
@@ -1058,7 +1017,7 @@
private byte[] getNormalizedValue() {
if (normalizedValue == null) {
- normalizedValue = toDn().toIrreversibleNormalizedByteString().toByteArray();
+ normalizedValue = toDn().toNormalizedByteString().toByteArray();
}
return normalizedValue;
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
index eb05a90..80d1337 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
@@ -257,6 +257,7 @@
}
/** {@inheritDoc} */
+ @Override
public int compareTo(final RDN rdn) {
// Identity.
if (this == rdn) {
@@ -373,6 +374,7 @@
*
* @return An iterator of the AVAs contained in this RDN.
*/
+ @Override
public Iterator<AVA> iterator() {
return Iterators.arrayIterator(avas);
}
@@ -421,7 +423,7 @@
* @param builder
* The builder to use to construct the normalized byte string.
* @return The normalized byte string representation.
- * @see DN#toIrreversibleNormalizedByteString()
+ * @see DN#toNormalizedByteString()
*/
ByteStringBuilder toNormalizedByteString(final ByteStringBuilder builder) {
switch (size()) {
@@ -445,30 +447,29 @@
}
/**
- * Returns the normalized readable string representation of this RDN.
+ * Retrieves a normalized string representation of this RDN.
* <p>
- * The representation is not a valid RDN.
+ * This representation is safe to use in an URL or in a file name.
+ * However, it is not a valid RDN and can't be reverted to a valid RDN.
*
- * @param builder
- * The builder to use to construct the normalized string.
- * @return The normalized readable string representation.
- * @see DN#toIrreversibleReadableString()
+ * @return The normalized string representation of this RDN.
+ * @see DN#toNormalizedUrlSafeString()
*/
- StringBuilder toNormalizedReadableString(final StringBuilder builder) {
+ StringBuilder toNormalizedUrlSafeString(final StringBuilder builder) {
switch (size()) {
case 0:
// Handle RDN.maxValue().
builder.append(RDN.AVA_CHAR_SEPARATOR);
break;
case 1:
- getFirstAVA().toNormalizedReadableString(builder);
+ getFirstAVA().toNormalizedUrlSafe(builder);
break;
default:
Iterator<AVA> it = getSortedAvas();
- it.next().toNormalizedReadableString(builder);
+ it.next().toNormalizedUrlSafe(builder);
while (it.hasNext()) {
builder.append(RDN.AVA_CHAR_SEPARATOR);
- it.next().toNormalizedReadableString(builder);
+ it.next().toNormalizedUrlSafe(builder);
}
break;
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
index 480e42c..1e023e6 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
@@ -187,7 +187,7 @@
private ByteString normalizeDN(final Schema schema, final String dnstring) throws DecodeException {
try {
DN dn = DN.valueOf(dnstring, schema.asNonStrictSchema());
- return dn.toIrreversibleNormalizedByteString();
+ return dn.toNormalizedByteString();
} catch (Exception e) {
logger.traceException(e);
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
index 71a36f5..d8381a3 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
@@ -43,7 +43,7 @@
throws DecodeException {
try {
DN dn = DN.valueOf(value.toString(), schema.asNonStrictSchema());
- return dn.toIrreversibleNormalizedByteString();
+ return dn.toNormalizedByteString();
} catch (final LocalizedIllegalArgumentException e) {
throw DecodeException.error(e.getMessageObject());
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
index 0297080..951cf84 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
@@ -57,7 +57,7 @@
try {
DN dn = DN.valueOf(stringValue.substring(0, dnEndPosition), schema.asNonStrictSchema());
return new ByteStringBuilder()
- .append(dn.toIrreversibleNormalizedByteString())
+ .append(dn.toNormalizedByteString())
.append(optionalUid).toByteString();
} catch (final LocalizedIllegalArgumentException e) {
throw DecodeException.error(e.getMessageObject());
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java b/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java
index 274ea6b..a16b124 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java
@@ -830,7 +830,7 @@
}
private static byte[] toNormalizedByteArray(DN dn) {
- return dn.toIrreversibleNormalizedByteString().toByteArray();
+ return dn.toNormalizedByteString().toByteArray();
}
private static byte[][] encodeEntry(final Entry entry) {
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java
index 65d539a..e151dab 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java
@@ -26,6 +26,8 @@
*/
package org.forgerock.opendj.ldap;
+import static java.lang.Integer.*;
+
import static org.fest.assertions.Assertions.*;
import static org.testng.Assert.*;
@@ -389,8 +391,8 @@
assertEquals(c.size(), 3);
- assertEquals(c.compareTo(p), 1);
- assertEquals(p.compareTo(c), -1);
+ assertEquals(signum(c.compareTo(p)), 1);
+ assertEquals(signum(p.compareTo(c)), -1);
assertTrue(p.isParentOf(c));
assertFalse(c.isParentOf(p));
@@ -666,8 +668,8 @@
assertEquals(p.size(), 3);
- assertEquals(p.compareTo(c), -1);
- assertEquals(c.compareTo(p), 1);
+ assertEquals(signum(p.compareTo(c)), -1);
+ assertEquals(signum(c.compareTo(p)), 1);
assertTrue(p.isParentOf(c));
assertFalse(c.isParentOf(p));
@@ -1005,12 +1007,12 @@
assertEquals(actual, "\\#cn\\=foo\\+sn\\=bar");
}
- /** Tests the {@link DN#toIrreversibleNormalizedByteString()} method. */
- @Test
- public void testToIrreversibleNormalizedByteStringWithRootDN() {
- ByteString actual = DN.rootDN().toIrreversibleNormalizedByteString();
- assertEquals(actual, ByteString.empty());
- }
+ /** Tests the {@link DN#toNormalizedByteString()} method. */
+ @Test
+ public void testToNormalizedByteStringWithRootDN() {
+ ByteString actual = DN.rootDN().toNormalizedByteString();
+ assertEquals(actual, ByteString.empty());
+ }
/** Tests the {@link DN#iterator()} method. */
@Test
@@ -1080,24 +1082,24 @@
}
@Test(dataProvider = "toIrreversibleNormalizedByteStringDataProvider")
- public void testToIrreversibleNormalizedByteString(String first, String second, int expectedCompareResult) {
- DN actual = DN.valueOf(first);
- DN expected = DN.valueOf(second);
- int cmp = actual.toIrreversibleNormalizedByteString().compareTo(expected.toIrreversibleNormalizedByteString());
- assertThat(Integer.signum(cmp)).isEqualTo(expectedCompareResult);
- }
+ public void testToNormalizedByteString(String first, String second, int expectedCompareResult) {
+ DN actual = DN.valueOf(first);
+ DN expected = DN.valueOf(second);
+ int cmp = actual.toNormalizedByteString().compareTo(expected.toNormalizedByteString());
+ assertThat(signum(cmp)).isEqualTo(expectedCompareResult);
+ }
/** Additional tests with testDNs data provider. */
- @Test(dataProvider = "testDNs")
- public void testToIrreversibleNormalizedByteString2(String one, String two, String three) {
- DN dn1 = DN.valueOf(one);
- DN dn2 = DN.valueOf(two);
- DN dn3 = DN.valueOf(three);
- int cmp = dn1.toIrreversibleNormalizedByteString().compareTo(dn2.toIrreversibleNormalizedByteString());
- assertThat(cmp).isEqualTo(0);
- int cmp2 = dn1.toIrreversibleNormalizedByteString().compareTo(dn3.toIrreversibleNormalizedByteString());
- assertThat(cmp2).isEqualTo(0);
- }
+ @Test(dataProvider = "testDNs")
+ public void testToNormalizedByteString2(String one, String two, String three) {
+ DN dn1 = DN.valueOf(one);
+ DN dn2 = DN.valueOf(two);
+ DN dn3 = DN.valueOf(three);
+ int cmp = dn1.toNormalizedByteString().compareTo(dn2.toNormalizedByteString());
+ assertThat(cmp).isEqualTo(0);
+ int cmp2 = dn1.toNormalizedByteString().compareTo(dn3.toNormalizedByteString());
+ assertThat(cmp2).isEqualTo(0);
+ }
@DataProvider
public Object[][] toIrreversibleReadableStringDataProvider() {
@@ -1134,19 +1136,19 @@
}
@Test(dataProvider = "toIrreversibleReadableStringDataProvider")
- public void testToIrreversibleReadableString(String dnAsString, String expectedReadableString) {
- DN actual = DN.valueOf(dnAsString);
- assertEquals(actual.toIrreversibleReadableString(), expectedReadableString);
- }
+ public void testToNormalizedUrlSafeString(String dnAsString, String expectedReadableString) {
+ DN actual = DN.valueOf(dnAsString);
+ assertEquals(actual.toNormalizedUrlSafeString(), expectedReadableString);
+ }
/** Additional tests with testDNs data provider. */
- @Test(dataProvider = "testDNs")
- public void testToIrreversibleReadableString2(String one, String two, String three) {
- DN dn1 = DN.valueOf(one);
- DN dn2 = DN.valueOf(two);
- DN dn3 = DN.valueOf(three);
- String irreversibleReadableString = dn1.toIrreversibleReadableString();
- assertEquals(irreversibleReadableString, dn2.toIrreversibleReadableString());
- assertEquals(irreversibleReadableString, dn3.toIrreversibleReadableString());
- }
+ @Test(dataProvider = "testDNs")
+ public void testToNormalizedUrlSafeString2(String one, String two, String three) {
+ DN dn1 = DN.valueOf(one);
+ DN dn2 = DN.valueOf(two);
+ DN dn3 = DN.valueOf(three);
+ String irreversibleReadableString = dn1.toNormalizedUrlSafeString();
+ assertEquals(irreversibleReadableString, dn2.toNormalizedUrlSafeString());
+ assertEquals(irreversibleReadableString, dn3.toNormalizedUrlSafeString());
+ }
}
--
Gitblit v1.10.0