Implemented choice in key case folding between lower, upper or none. LDAP-188
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user