mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
04.23.2013 ea9338f20259f92ccb818876e27cd83908cef0d0
Backport fix for OPENDJ-1200: Upgrade tool loses one ds-cfg-character-set value

*change the default syntax and matching rule for unrecognized attribute types to OctetString (resulting in case exact matching)
* re-enable test case which exposes OPENDJ-1200
* add the ability to override the default syntax and matching rule in the SchemaBuilder
* add unit tests for above, plus additional unit tests fixes in the DN matching rule.
8 files modified
377 ■■■■ changed files
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java 10 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java 9 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java 126 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java 92 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java 25 ●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleTest.java 22 ●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/SchemaBuilderTestCase.java 46 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFEntryReaderTestCase.java 47 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Portions copyright 2011-2012 ForgeRock AS.
 *      Portions copyright 2011-2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
@@ -175,10 +175,12 @@
     * attribute will be the normalized attribute type name followed by the
     * suffix "-oid".
     *
     * @param schema
     *            The parent schema.
     * @param name
     *            The name of the place-holder attribute type.
     */
    AttributeType(final String name) {
    AttributeType(final Schema schema, final String name) {
        super("", Collections.<String, List<String>> emptyMap());
        final StringBuilder builder = new StringBuilder(name.length() + 4);
@@ -190,12 +192,12 @@
        this.isObsolete = false;
        this.superiorTypeOID = null;
        this.superiorType = null;
        this.equalityMatchingRule = Schema.getDefaultMatchingRule();
        this.equalityMatchingRule = schema.getDefaultMatchingRule();
        this.equalityMatchingRuleOID = equalityMatchingRule.getOID();
        this.orderingMatchingRuleOID = null;
        this.substringMatchingRuleOID = null;
        this.approximateMatchingRuleOID = null;
        this.syntax = Schema.getDefaultSyntax();
        this.syntax = schema.getDefaultSyntax();
        this.syntaxOID = syntax.getOID();
        this.isSingleValue = false;
        this.isCollective = false;
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
@@ -22,6 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
@@ -370,10 +371,10 @@
        }
        if (impl == null) {
            impl = Schema.getDefaultMatchingRule().impl;
            final LocalizableMessage message =
                    WARN_MATCHING_RULE_NOT_IMPLEMENTED1.get(getNameOrOID(), Schema
                            .getDefaultMatchingRule().getOID());
            impl = schema.getDefaultMatchingRule().impl;
            final LocalizableMessage message = WARN_MATCHING_RULE_NOT_IMPLEMENTED1
                    .get(getNameOrOID(), schema.getDefaultMatchingRule()
                            .getOID());
            warnings.add(message);
        }
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011-2012 ForgeRock AS
 *      Portions copyright 2011-2013 ForgeRock AS
 */
package org.forgerock.opendj.ldap.schema;
@@ -95,13 +95,21 @@
            return false;
        }
        public Syntax getDefaultSyntax() {
            return Schema.getCoreSchema().getDefaultSyntax();
        }
        public MatchingRule getDefaultMatchingRule() {
            return Schema.getCoreSchema().getDefaultMatchingRule();
        }
        @Override
        public AttributeType getAttributeType(final String name) {
        public AttributeType getAttributeType(final Schema schema, final String name) {
            if (isStrict) {
                throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name));
            } else {
                // Return a place-holder.
                return new AttributeType(name);
                return new AttributeType(schema, name);
            }
        }
@@ -234,9 +242,9 @@
        }
        @Override
        public Syntax getSyntax(final String numericOID) {
        public Syntax getSyntax(final Schema schema, final String numericOID) {
            // Fake up a syntax substituted by the default syntax.
            return new Syntax(numericOID);
            return new Syntax(schema, numericOID);
        }
        @Override
@@ -308,7 +316,11 @@
        boolean allowZeroLengthDirectoryStrings();
        AttributeType getAttributeType(String name);
        MatchingRule getDefaultMatchingRule();
        Syntax getDefaultSyntax();
        AttributeType getAttributeType(Schema schema, String name);
        Collection<AttributeType> getAttributeTypes();
@@ -360,7 +372,7 @@
        String getSchemaName();
        Syntax getSyntax(String numericOID);
        Syntax getSyntax(Schema schema, String numericOID);
        Collection<Syntax> getSyntaxes();
@@ -408,10 +420,18 @@
            return strictImpl.allowZeroLengthDirectoryStrings();
        }
        public Syntax getDefaultSyntax() {
            return strictImpl.getDefaultSyntax();
        }
        public MatchingRule getDefaultMatchingRule() {
            return strictImpl.getDefaultMatchingRule();
        }
        @Override
        public AttributeType getAttributeType(final String name) {
        public AttributeType getAttributeType(final Schema schema, final String name) {
            final AttributeType type = strictImpl.getAttributeType0(name);
            return type != null ? type : new AttributeType(name);
            return type != null ? type : new AttributeType(schema, name);
        }
        @Override
@@ -540,11 +560,11 @@
        }
        @Override
        public Syntax getSyntax(final String numericOID) {
        public Syntax getSyntax(final Schema schema, final String numericOID) {
            if (!strictImpl.hasSyntax(numericOID)) {
                return new Syntax(numericOID);
                return new Syntax(schema, numericOID);
            }
            return strictImpl.getSyntax(numericOID);
            return strictImpl.getSyntax(schema, numericOID);
        }
        @Override
@@ -609,55 +629,37 @@
    private static final class StrictImpl implements Impl {
        private final Map<Integer, DITStructureRule> id2StructureRules;
        private final Map<String, List<AttributeType>> name2AttributeTypes;
        private final Map<String, List<DITContentRule>> name2ContentRules;
        private final Map<String, List<MatchingRule>> name2MatchingRules;
        private final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses;
        private final Map<String, List<NameForm>> name2NameForms;
        private final Map<String, List<ObjectClass>> name2ObjectClasses;
        private final Map<String, List<DITStructureRule>> name2StructureRules;
        private final Map<String, List<DITStructureRule>> nameForm2StructureRules;
        private final Map<String, AttributeType> numericOID2AttributeTypes;
        private final Map<String, DITContentRule> numericOID2ContentRules;
        private final Map<String, MatchingRule> numericOID2MatchingRules;
        private final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses;
        private final Map<String, NameForm> numericOID2NameForms;
        private final Map<String, ObjectClass> numericOID2ObjectClasses;
        private final Map<String, Syntax> numericOID2Syntaxes;
        private final Map<String, List<NameForm>> objectClass2NameForms;
        private final List<LocalizableMessage> warnings;
        private final String schemaName;
        private final boolean allowMalformedJPEGPhotos;
        private final boolean allowNonStandardTelephoneNumbers;
        private final boolean allowZeroLengthDirectoryStrings;
        private final boolean allowMalformedNamesAndOptions;
        private final Syntax defaultSyntax;
        private final MatchingRule defaultMatchingRule;
        StrictImpl(final String schemaName, final boolean allowMalformedNamesAndOptions,
                final boolean allowMalformedJPEGPhotos,
                final boolean allowNonStandardTelephoneNumbers,
                final boolean allowZeroLengthDirectoryStrings,
                final Syntax defaultSyntax,
                final MatchingRule defaultMatchingRule,
                final Map<String, Syntax> numericOID2Syntaxes,
                final Map<String, MatchingRule> numericOID2MatchingRules,
                final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
@@ -681,6 +683,8 @@
            this.allowMalformedJPEGPhotos = allowMalformedJPEGPhotos;
            this.allowNonStandardTelephoneNumbers = allowNonStandardTelephoneNumbers;
            this.allowZeroLengthDirectoryStrings = allowZeroLengthDirectoryStrings;
            this.defaultSyntax = defaultSyntax;
            this.defaultMatchingRule = defaultMatchingRule;
            this.numericOID2Syntaxes = Collections.unmodifiableMap(numericOID2Syntaxes);
            this.numericOID2MatchingRules = Collections.unmodifiableMap(numericOID2MatchingRules);
            this.numericOID2MatchingRuleUses =
@@ -718,8 +722,16 @@
            return allowZeroLengthDirectoryStrings;
        }
        public Syntax getDefaultSyntax() {
            return defaultSyntax;
        }
        public MatchingRule getDefaultMatchingRule() {
            return defaultMatchingRule;
        }
        @Override
        public AttributeType getAttributeType(final String name) {
        public AttributeType getAttributeType(final Schema schema, final String name) {
            final AttributeType type = getAttributeType0(name);
            if (type != null) {
                return type;
@@ -963,7 +975,7 @@
        }
        @Override
        public Syntax getSyntax(final String numericOID) {
        public Syntax getSyntax(final Schema schema, final String numericOID) {
            final Syntax syntax = numericOID2Syntaxes.get(numericOID);
            if (syntax == null) {
                throw new UnknownSchemaElementException(WARN_SYNTAX_UNKNOWN.get(numericOID));
@@ -1317,20 +1329,14 @@
        return new SchemaBuilder(entry).toSchema();
    }
    static MatchingRule getDefaultMatchingRule() {
        return CoreSchema.getCaseIgnoreMatchingRule();
    }
    static Syntax getDefaultSyntax() {
        return CoreSchema.getDirectoryStringSyntax();
    }
    private final Impl impl;
    Schema(final String schemaName, final boolean allowMalformedNamesAndOptions,
            final boolean allowMalformedJPEGPhotos,
            final boolean allowNonStandardTelephoneNumbers,
            final boolean allowZeroLengthDirectoryStrings,
            final Syntax defaultSyntax,
            final MatchingRule defaultMatchingRule,
            final Map<String, Syntax> numericOID2Syntaxes,
            final Map<String, MatchingRule> numericOID2MatchingRules,
            final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
@@ -1350,9 +1356,9 @@
            final Map<String, List<DITStructureRule>> nameForm2StructureRules,
            final List<LocalizableMessage> warnings) {
        impl =
                new StrictImpl(schemaName, allowMalformedNamesAndOptions,
                        allowMalformedJPEGPhotos, allowNonStandardTelephoneNumbers,
                        allowZeroLengthDirectoryStrings, numericOID2Syntaxes,
                new StrictImpl(schemaName, allowMalformedNamesAndOptions, allowMalformedJPEGPhotos,
                        allowNonStandardTelephoneNumbers, allowZeroLengthDirectoryStrings,
                        defaultSyntax, defaultMatchingRule, numericOID2Syntaxes,
                        numericOID2MatchingRules, numericOID2MatchingRuleUses,
                        numericOID2AttributeTypes, numericOID2ObjectClasses, numericOID2NameForms,
                        numericOID2ContentRules, id2StructureRules, name2MatchingRules,
@@ -1474,6 +1480,28 @@
    }
    /**
     * Returns the default matching rule which will be used when parsing
     * unrecognized attributes.
     *
     * @return The default matching rule which will be used when parsing
     *         unrecognized attributes.
     */
    public MatchingRule getDefaultMatchingRule() {
        return impl.getDefaultMatchingRule();
    }
    /**
     * Returns the default syntax which will be used when parsing unrecognized
     * attributes.
     *
     * @return The default syntax which will be used when parsing unrecognized
     *         attributes.
     */
    public Syntax getDefaultSyntax() {
        return impl.getDefaultSyntax();
    }
    /**
     * 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
@@ -1492,7 +1520,7 @@
     * @see AttributeType#isPlaceHolder()
     */
    public AttributeType getAttributeType(final String name) {
        return impl.getAttributeType(name);
        return impl.getAttributeType(this, name);
    }
    /**
@@ -1824,7 +1852,7 @@
     *             found or if the provided name is ambiguous.
     */
    public Syntax getSyntax(final String numericOID) {
        return impl.getSyntax(numericOID);
        return impl.getSyntax(this, numericOID);
    }
    /**
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -174,6 +174,9 @@
    private boolean allowMalformedJPEGPhotos;
    private String defaultSyntaxOID;
    private String defaultMatchingRuleOID;
    // A schema which should be copied into this builder on any mutation.
    private Schema copyOnWriteSchema = null;
@@ -2285,6 +2288,74 @@
    }
    /**
     * Sets the default syntax which will be used when parsing unrecognized
     * attributes.
     * <p>
     * By default the {@link CoreSchema#getOctetStringSyntax() OctetString}
     * syntax will be used.
     *
     * @param syntax
     *            The default syntax which will be used when parsing
     *            unrecognized attributes.
     * @return A reference to this {@code SchemaBuilder}.
     */
    public SchemaBuilder defaultSyntax(final Syntax syntax) {
        return defaultSyntax(syntax.getOID());
    }
    /**
     * Sets the default matching rule which will be used when parsing
     * unrecognized attributes.
     * <p>
     * By default the {@link CoreSchema#getOctetStringMatchingRule()
     * OctetString} matching rule will be used.
     *
     * @param rule
     *            The default matching rule which will be used when parsing
     *            unrecognized attributes.
     * @return A reference to this {@code SchemaBuilder}.
     */
    public SchemaBuilder defaultMatchingRule(final MatchingRule rule) {
        return defaultMatchingRule(rule.getOID());
    }
    /**
     * Sets the default syntax which will be used when parsing unrecognized
     * attributes.
     * <p>
     * By default the {@link CoreSchema#getOctetStringSyntax() OctetString}
     * syntax will be used.
     *
     * @param syntaxOID
     *            The default syntax which will be used when parsing
     *            unrecognized attributes.
     * @return A reference to this {@code SchemaBuilder}.
     */
    public SchemaBuilder defaultSyntax(final String syntaxOID) {
        lazyInitBuilder();
        this.defaultSyntaxOID = syntaxOID;
        return this;
    }
    /**
     * Sets the default matching rule which will be used when parsing
     * unrecognized attributes.
     * <p>
     * By default the {@link CoreSchema#getOctetStringMatchingRule()
     * OctetString} matching rule will be used.
     *
     * @param ruleOID
     *            The default matching rule which will be used when parsing
     *            unrecognized attributes.
     * @return A reference to this {@code SchemaBuilder}.
     */
    public SchemaBuilder defaultMatchingRule(final String ruleOID) {
        lazyInitBuilder();
        this.defaultMatchingRuleOID = ruleOID;
        return this;
    }
    /**
     * Removes the named attribute type from this schema builder.
     *
     * @param name
@@ -2500,17 +2571,26 @@
            localSchemaName = String.format("Schema#%d", NEXT_SCHEMA_ID.getAndIncrement());
        }
        Syntax defaultSyntax = numericOID2Syntaxes.get(defaultSyntaxOID);
        if (defaultSyntax == null) {
            defaultSyntax = Schema.getCoreSchema().getDefaultSyntax();
        }
        MatchingRule defaultMatchingRule = numericOID2MatchingRules.get(defaultMatchingRuleOID);
        if (defaultMatchingRule == null) {
            defaultMatchingRule = Schema.getCoreSchema().getDefaultMatchingRule();
        }
        final Schema schema =
                new Schema(localSchemaName, allowMalformedNamesAndOptions,
                        allowMalformedJPEGPhotos, allowNonStandardTelephoneNumbers,
                        allowZeroLengthDirectoryStrings, numericOID2Syntaxes,
                        numericOID2MatchingRules, numericOID2MatchingRuleUses,
                        allowZeroLengthDirectoryStrings, defaultSyntax, defaultMatchingRule,
                        numericOID2Syntaxes, numericOID2MatchingRules, numericOID2MatchingRuleUses,
                        numericOID2AttributeTypes, numericOID2ObjectClasses, numericOID2NameForms,
                        numericOID2ContentRules, id2StructureRules, name2MatchingRules,
                        name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
                        name2NameForms, name2ContentRules, name2StructureRules,
                        objectClass2NameForms, nameForm2StructureRules, warnings);
        validate(schema);
        // Re-init this builder so that it can continue to be used afterwards.
@@ -2782,6 +2862,8 @@
            allowMalformedJPEGPhotos = true;
            allowNonStandardTelephoneNumbers = true;
            allowZeroLengthDirectoryStrings = false;
            defaultSyntaxOID = SchemaConstants.SYNTAX_OCTET_STRING_OID;
            defaultMatchingRuleOID = SchemaConstants.EMR_OCTET_STRING_OID;
            numericOID2Syntaxes = new LinkedHashMap<String, Syntax>();
            numericOID2MatchingRules = new LinkedHashMap<String, MatchingRule>();
@@ -2813,6 +2895,8 @@
            allowMalformedJPEGPhotos = copyOnWriteSchema.allowMalformedJPEGPhotos();
            allowNonStandardTelephoneNumbers = copyOnWriteSchema.allowNonStandardTelephoneNumbers();
            allowZeroLengthDirectoryStrings = copyOnWriteSchema.allowZeroLengthDirectoryStrings();
            defaultSyntaxOID = copyOnWriteSchema.getDefaultSyntax().getOID();
            defaultMatchingRuleOID = copyOnWriteSchema.getDefaultMatchingRule().getOID();
            copyOnWriteSchema = null;
        }
@@ -2826,6 +2910,8 @@
        this.allowMalformedJPEGPhotos = true;
        this.allowNonStandardTelephoneNumbers = true;
        this.allowZeroLengthDirectoryStrings = false;
        this.defaultSyntaxOID = null;
        this.defaultMatchingRuleOID = null;
        this.numericOID2Syntaxes = null;
        this.numericOID2MatchingRules = null;
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java
@@ -22,6 +22,7 @@
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
@@ -63,14 +64,24 @@
    private Schema schema;
    private SyntaxImpl impl;
    Syntax(final String oid) {
        super("", Collections.singletonMap("X-SUBST", Collections.singletonList(Schema
    /**
     * Creates a syntax representing an unrecognized syntax and whose
     * implementation is substituted by the schema's default syntax.
     *
     * @param schema
     *            The parent schema.
     * @param oid
     *            The numeric OID of the unrecognized syntax.
     */
    Syntax(final Schema schema, final String oid) {
        super("", Collections.singletonMap("X-SUBST", Collections.singletonList(schema
                .getDefaultSyntax().getOID())));
        Validator.ensureNotNull(oid);
        this.oid = oid;
        this.definition = buildDefinition();
        this.impl = Schema.getDefaultSyntax().impl;
        this.schema = schema;
        this.impl = schema.getDefaultSyntax().impl;
    }
    Syntax(final String oid, final String description,
@@ -307,10 +318,10 @@
            }
            if (impl == null) {
                impl = Schema.getDefaultSyntax().impl;
                final LocalizableMessage message =
                        WARN_ATTR_SYNTAX_NOT_IMPLEMENTED1.get(getDescription(), oid, Schema
                                .getDefaultSyntax().getOID());
                impl = schema.getDefaultSyntax().impl;
                final LocalizableMessage message = WARN_ATTR_SYNTAX_NOT_IMPLEMENTED1
                        .get(getDescription(), oid, schema.getDefaultSyntax()
                                .getOID());
                warnings.add(message);
            }
        }
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleTest.java
@@ -22,6 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
@@ -29,9 +30,6 @@
import static org.forgerock.opendj.ldap.schema.SchemaConstants.EMR_DN_OID;
import static org.testng.Assert.assertEquals;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.testng.annotations.DataProvider;
@@ -112,7 +110,11 @@
            { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107", ConditionResult.TRUE },
            { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius", "ou=\u55b6\u696d\u90e8,o=airius",
                ConditionResult.TRUE },
            { "photo=\\ john \\ ,dc=com", "photo=\\ john \\ ,dc=com", ConditionResult.TRUE },
            { "cn=\\ john \\ ,dc=com", "cn=\\ john \\ ,dc=com", ConditionResult.TRUE },
            { "caseexact=UPPER,dc=COM", "caseexact=UPPER,dc=com", ConditionResult.TRUE },
            { "caseexact=upper,dc=COM", "caseexact=UPPER,dc=com", ConditionResult.FALSE },
            { "caseexact=UPPER,dc=COM", "caseexact=upper,dc=com", ConditionResult.FALSE },
            { "caseexact=lower,dc=COM", "caseexact=lower,dc=com", ConditionResult.TRUE },
            { "AB-global=", "ab-global=", ConditionResult.TRUE },
            { "OU= Sales + CN = J. Smith ,DC=example,DC=net",
                "cn=j. smith+ou=sales,dc=example,dc=net", ConditionResult.TRUE },
@@ -167,10 +169,12 @@
                // Unicode codepoints from 0000-0008 are mapped to nothing.
                "cn=hi" },
            { "1.1.1=", "1.1.1=" },
            { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107" },
            { "CN=Lu\\C4\\8Di\\C4\\87", "cn=luc\u030cic\u0301" },
            { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius",
                "o=airius\u0000ou=\u55b6\u696d\u90e8" },
            { "photo=\\ john \\ ,dc=com", "dc=com\u0000photo=john" },
            { "cn=\\ john \\ ,dc=com", "dc=com\u0000cn=john" },
            { "caseexact=UPPER,dc=COM", "dc=com\u0000caseexact=UPPER" },
            { "caseexact=mIxEd,dc=COM", "dc=com\u0000caseexact=mIxEd" },
            { "AB-global=", "ab-global=" },
            { "OU= Sales + CN = J. Smith ,DC=example,DC=net",
                "dc=net\u0000dc=example\u0000cn=j. smith\u0001ou=sales" },
@@ -186,13 +190,11 @@
     * Test the normalized values
     */
    @Test(dataProvider = "testDNs")
    public void matchingRules(final String value1, final String value2) throws Exception {
    public void testNormalization(final String value1, final String value2) throws Exception {
        final MatchingRule rule = getRule();
        final ByteString normalizedValue1 =
                rule.normalizeAttributeValue(ByteString.valueOf(value1));
        final ByteString expectedValue =
                ByteString.valueOf(Normalizer.normalize(value2, Form.NFKD));
        final ByteString expectedValue = ByteString.valueOf(value2);
        assertEquals(normalizedValue1, expectedValue);
    }
}
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/schema/SchemaBuilderTestCase.java
@@ -21,7 +21,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldap.schema;
@@ -210,6 +210,9 @@
        assertThat(schema.getObjectClasses()).isEmpty();
        assertThat(schema.getSyntaxes()).isEmpty();
        assertThat(schema.getWarnings()).isEmpty();
        assertThat(schema.getDefaultSyntax()).isEqualTo(CoreSchema.getOctetStringSyntax());
        assertThat(schema.getDefaultMatchingRule()).isEqualTo(
                CoreSchema.getOctetStringMatchingRule());
        // Could go on...
    }
@@ -1960,7 +1963,46 @@
        assertThat(sc.getNameForms()).isNotNull();
        assertThat(sc.getNameForms()).isEmpty();
        connection.close();
    }
    @Test
    public void testDefaultSyntax() {
        final Schema schema =
                new SchemaBuilder(Schema.getCoreSchema()).toSchema().asNonStrictSchema();
        assertThat(schema.getDefaultSyntax()).isEqualTo(CoreSchema.getOctetStringSyntax());
        assertThat(schema.getAttributeType("dummy").getSyntax()).isEqualTo(
                CoreSchema.getOctetStringSyntax());
    }
    @Test
    public void testOverrideDefaultSyntax() {
        final Schema schema =
                new SchemaBuilder(Schema.getCoreSchema()).defaultSyntax(
                        CoreSchema.getDirectoryStringSyntax()).toSchema().asNonStrictSchema();
        assertThat(schema.getDefaultSyntax()).isEqualTo(CoreSchema.getDirectoryStringSyntax());
        assertThat(schema.getAttributeType("dummy").getSyntax()).isEqualTo(
                CoreSchema.getDirectoryStringSyntax());
    }
    @Test
    public void testDefaultMatchingRule() {
        final Schema schema =
                new SchemaBuilder(Schema.getCoreSchema()).toSchema().asNonStrictSchema();
        assertThat(schema.getDefaultMatchingRule()).isEqualTo(
                CoreSchema.getOctetStringMatchingRule());
        assertThat(schema.getAttributeType("dummy").getEqualityMatchingRule()).isEqualTo(
                CoreSchema.getOctetStringMatchingRule());
    }
    @Test
    public void testOverrideMatchingRule() {
        final Schema schema =
                new SchemaBuilder(Schema.getCoreSchema()).defaultMatchingRule(
                        CoreSchema.getCaseIgnoreMatchingRule()).toSchema().asNonStrictSchema();
        assertThat(schema.getDefaultMatchingRule()).isEqualTo(CoreSchema.getCaseIgnoreMatchingRule());
        assertThat(schema.getAttributeType("dummy").getEqualityMatchingRule()).isEqualTo(
                CoreSchema.getCaseIgnoreMatchingRule());
    }
}
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFEntryReaderTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2013 ForgeRock AS.
 */
package org.forgerock.opendj.ldif;
@@ -52,6 +52,7 @@
import org.forgerock.opendj.ldap.schema.SchemaValidationPolicy.Policy;
import org.testng.Assert;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyListOf;
@@ -1652,4 +1653,48 @@
    public void testValueOfLDIFEntryDoesntAllowNull() throws Exception {
        LDIFEntryReader.valueOfLDIFEntry((String[]) null);
    }
    /**
     * Tries to read an entry composed by multi-valued attributes. The
     * multi-valued attributes contains an interesting case where two of them
     * represents the same value, one in uppercase and the other in lower case.
     *
     * @throws Exception
     */
    @Test
    public void testLDIFEntryReaderMultiplesAttributeValuesDifferentLetterCase() throws Exception {
        // @formatter:off
        final String[] strEntry = {
            "dn: cn=Character Set,cn=Password Validators,cn=config",
            "objectClass: ds-cfg-character-set-password-validator",
            "objectClass: ds-cfg-password-validator",
            "objectClass: top",
            "ds-cfg-enabled: true",
            "ds-cfg-java-class: org.opends.server.extensions.CharacterSetPasswordValidator",
            "ds-cfg-allow-unclassified-characters: true",
            "ds-cfg-character-set: 1:abcdefghijklmnopqrstuvwxyz",
            "ds-cfg-character-set: 1:ABCDEFGHIJKLMNOPQRSTUVWXYZ",
            "ds-cfg-character-set: 1:0123456789",
            "ds-cfg-character-set: 1:~!@#$%^&*()-_=+[]{}|;:,.<>/?",
            "cn: Character Set"
        };
        // @formatter:on
        final String path = TestCaseUtils.createTempFile(strEntry);
        final FileInputStream in = new FileInputStream(path);
        final LDIFEntryReader reader = new LDIFEntryReader(in);
        try {
            assertThat(reader.hasNext());
            final Entry entry = reader.readEntry();
            assertThat(entry.getName().toString()).isEqualTo(
                    "cn=Character Set,cn=Password Validators,cn=config");
            // List the attributes : objectClass ds-cfg-enabled ds-cfg-java-class
            // ds-cfg-allow-unclassified-characters ds-cfg-character-set cn
            assertThat(entry.getAttributeCount()).isEqualTo(6);
            assertThat(entry.getAttribute("ds-cfg-character-set")).isNotEmpty();
            assertThat(entry.getAttribute("ds-cfg-character-set").toArray().length).isEqualTo(4);
            assertThat(reader.hasNext()).isFalse();
        } finally {
            reader.close();
        }
    }
}