Implemented choice in key case folding between lower, upper or none. LDAP-188

This commit is contained in:
Ulrik Sandberg
2010-11-15 22:52:43 +00:00
parent fcd02162b8
commit 8b41a0a4ec
5 changed files with 129 additions and 26 deletions

View File

@@ -12,7 +12,7 @@ http://www.ietf.org/rfc/rfc2256.txt
http://www.ietf.org/rfc/rfc2696.txt
http://www.ietf.org/rfc/rfc2829.txt
Changes in version 1.3.1 (October 2010)
Changes in version 1.3.1 (November 2010)
-------------------------------------------
* Added an object-directory mapping framework (ODM). Contributed by Paul
Harvey.
@@ -47,12 +47,17 @@ Changes in version 1.3.1 (October 2010)
* Authentication methods now log problems at level INFO rather than ERROR.
(LDAP-170)
* It's now possible to control the case folding of attribute keys in
DistinguishedName by setting the system property
DistinguishedName.KEY_CASE_FOLD_PROPERTY to one of "lower", "upper", or
"none". (LDAP-188)
* DIGEST-MD5 SASL authentication mechanism is now supported, as specified by
RFC 2829 (see http://www.ietf.org/rfc/rfc2829.txt, section 4). (LDAP-173)
Contributed by Marvin S. Addison.
* DefaultDirObjectFactory calls a Java5 version of the IllegalArgumentException
constructor. (LDAP 196).
constructor. (LDAP 196)
* DirContextAdapter JavaDoc now states clearly that several methods are not
implemented on purpose. (LDAP-208)

View File

@@ -95,24 +95,49 @@ import org.springframework.util.Assert;
*/
public class DistinguishedName implements Name {
/**
* System property that will be inspected to determine whether toString will
* format the DN with spaces after each comma or use a more compact
* representation, i.e.:
* System property that will be inspected to determine whether
* {@link #toString()} will format the DN with spaces after each comma or
* use a more compact representation, i.e.:
* <code>uid=adam.skogman, ou=People, dc=jayway, dc=se</code> rather than
* <code>uid=adam.skogman,ou=People,dc=jayway,dc=se</code>. Default is
* compact representation.
* <code>uid=adam.skogman,ou=People,dc=jayway,dc=se</code>. A value other
* than null or blank will trigger the spaced format. Default is the compact
* representation.
* <p>
* Valid values are:
* <ul>
* <li>blank or null (property not set)</li>
* <li>any non-blank value</li>
* </ul>
* @since 1.3
* @see #toCompactString()
*/
public static final String SPACED_DN_FORMAT_PROPERTY = "org.springframework.ldap.core.spacedDnFormat";
/**
* System property that will be inspected to determine whether creating a
* DistinguishedName will leave the keys as they were in the original String
* or convert the keys to lowercase. Default is to convert the keys to
* DistinguishedName will convert the keys to <em>lowercase</em>, convert
* the keys to <em>uppercase</em>, or leave the keys as they were in the
* original String, ie <em>none</em>. Default is to convert the keys to
* lowercase.
* <p>
* Valid values are:
* <ul>
* <li>"lower" or blank or null (property not set)</li>
* <li>"upper"</li>
* <li>"none"</li>
* </ul>
* @since 1.3.1
* @see #KEY_CASE_FOLD_LOWER
* @see #KEY_CASE_FOLD_UPPER
* @see #KEY_CASE_FOLD_NONE
*/
public static final String PRESERVE_KEY_CASE_PROPERTY = "org.springframework.ldap.core.preserveKeyCase";
public static final String KEY_CASE_FOLD_PROPERTY = "org.springframework.ldap.core.keyCaseFold";
public static final String KEY_CASE_FOLD_LOWER = "lower";
public static final String KEY_CASE_FOLD_UPPER = "upper";
public static final String KEY_CASE_FOLD_NONE = "none";
private static final Log log = LogFactory.getLog(DistinguishedName.class);

View File

@@ -21,6 +21,8 @@ import java.net.URISyntaxException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Represents part of an LdapRdn. As specified in RFC2253 an LdapRdn may be
@@ -33,6 +35,8 @@ import org.apache.commons.lang.Validate;
public class LdapRdnComponent implements Comparable, Serializable {
private static final long serialVersionUID = -3296747972616243038L;
private static final Log log = LogFactory.getLog(LdapRdnComponent.class);
public static final boolean DONT_DECODE_VALUE = false;
private String key;
@@ -52,27 +56,35 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Constructs an LdapRdnComponent, optionally decoding the value.
* <p>
* If the System property
* <code>org.springframework.ldap.core.preserveKeyCase</code> is set to
* "true", the keys will preserve their original case. Default is to convert
* them to lowercase.
* Depending on the value of the "key case fold" System property, the keys
* will be lowercased, uppercased, or preserve their original case. Default
* is to convert them to lowercase.
*
* @param key the Attribute name.
* @param value the Attribute value.
* @param decodeValue if <code>true</code> the value is decoded (typically
* used when a DN is parsed from a String), otherwise the value is used as
* specified.
* @see DistinguishedName#PRESERVE_KEY_CASE_PROPERTY
* @see DistinguishedName#KEY_CASE_FOLD_PROPERTY
*/
public LdapRdnComponent(String key, String value, boolean decodeValue) {
Validate.notEmpty(key, "Key must not be empty");
Validate.notEmpty(value, "Value must not be empty");
String preserveKeyCase = System.getProperty(DistinguishedName.PRESERVE_KEY_CASE_PROPERTY);
if (StringUtils.isBlank(preserveKeyCase)) {
String caseFold = System.getProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
if (StringUtils.isBlank(caseFold) || caseFold.equals(DistinguishedName.KEY_CASE_FOLD_LOWER)) {
this.key = StringUtils.lowerCase(key);
} else {
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) {
this.key = StringUtils.upperCase(key);
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
this.key = key;
} else {
log
.warn("\"" + caseFold + "\" invalid property value for " + DistinguishedName.KEY_CASE_FOLD_PROPERTY
+ "; expected \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\", \""
+ DistinguishedName.KEY_CASE_FOLD_UPPER + "\", or \""
+ DistinguishedName.KEY_CASE_FOLD_NONE + "\"");
this.key = StringUtils.lowerCase(key);
}
if (decodeValue) {
this.value = LdapEncoder.nameDecode(value);

View File

@@ -582,18 +582,79 @@ public class DistinguishedNameTest extends TestCase {
}
}
public void testPreserveKeyCasePropertyTrueShouldNotEqualLowerCasedKeys() throws Exception {
public void testKeyCaseFoldNoneShouldEqualOriginalCasedKeys() throws Exception {
try {
DistinguishedName name = new DistinguishedName("ou=foo,Ou=bar,oU=baz,OU=bim");
String dnString = "ou=foo,Ou=bar,oU=baz,OU=bim";
DistinguishedName name = new DistinguishedName(dnString);
// First check the default
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
System.setProperty(DistinguishedName.PRESERVE_KEY_CASE_PROPERTY, "true");
name = new DistinguishedName("ou=foo,Ou=bar,oU=baz,OU=bim");
assertEquals("ou=foo,Ou=bar,oU=baz,OU=bim", name.toString());
System.setProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY, DistinguishedName.KEY_CASE_FOLD_NONE);
name = new DistinguishedName(dnString);
System.out.println(dnString + " folded as \"" + DistinguishedName.KEY_CASE_FOLD_NONE + "\": " + name);
assertEquals(dnString, name.toString());
}
finally {
// Always restore the system setting
System.setProperty(DistinguishedName.PRESERVE_KEY_CASE_PROPERTY, "");
System.clearProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
}
}
public void testKeyCaseFoldUpperShouldEqualUpperCasedKeys() throws Exception {
try {
String dnString = "ou=foo,Ou=bar,oU=baz,OU=bim";
DistinguishedName name = new DistinguishedName(dnString);
// First check the default
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
System.setProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY, DistinguishedName.KEY_CASE_FOLD_UPPER);
name = new DistinguishedName(dnString);
System.out.println(dnString + " folded as \"" + DistinguishedName.KEY_CASE_FOLD_UPPER + "\": " + name);
assertEquals("OU=foo,OU=bar,OU=baz,OU=bim", name.toString());
}
finally {
// Always restore the system setting
System.clearProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
}
}
public void testKeyCaseFoldLowerShouldEqualLowerCasedKeys() throws Exception {
try {
String dnString = "ou=foo,Ou=bar,oU=baz,OU=bim";
DistinguishedName name = new DistinguishedName(dnString);
// First check the default
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
System.setProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY, DistinguishedName.KEY_CASE_FOLD_LOWER);
name = new DistinguishedName(dnString);
System.out.println(dnString + " folded as \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\": " + name);
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
}
finally {
// Always restore the system setting
System.clearProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
}
}
public void testKeyCaseFoldNonsenseShoulddefaultToLowerCasedKeysAndLogWarning() throws Exception {
try {
String dnString = "ou=foo,Ou=bar,oU=baz,OU=bim";
DistinguishedName name = new DistinguishedName(dnString);
// First check the default
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
System.setProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY, "whatever");
name = new DistinguishedName(dnString);
System.out.println(dnString + " folded as \"whatever\": " + name);
assertEquals("ou=foo,ou=bar,ou=baz,ou=bim", name.toString());
}
finally {
// Always restore the system setting
System.clearProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
}
}
}

View File

@@ -173,7 +173,7 @@ public class LdapTemplateModifyITest extends AbstractLdapTemplateIntegrationTest
tested.modifyAttributes(ctx);
// without this, the member added above will not be removed and the test fails
System.setProperty(DistinguishedName.PRESERVE_KEY_CASE_PROPERTY, Boolean.TRUE.toString());
System.setProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY, DistinguishedName.KEY_CASE_FOLD_NONE);
ctx = tested.lookupContext(dn);
ctx.removeAttributeValue("uniqueMember", new DistinguishedName(upperCasedName).toCompactString());
@@ -189,7 +189,7 @@ public class LdapTemplateModifyITest extends AbstractLdapTemplateIntegrationTest
assertEquals("3", "cn=Some Person3,ou=company1,c=Sweden,dc=jayway,dc=se", attributes[3]);
}
finally {
System.setProperty(DistinguishedName.PRESERVE_KEY_CASE_PROPERTY, "");
System.clearProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
}
}