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

Matthew Swift
11.13.2013 c865a97e6eec7f757af36688f95893ef520d8023
Changes for OPENDJ-691: Implement add/create support
* add toLDAP support for default mapper
* code cleanup.
5 files modified
275 ■■■■ changed files
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java 23 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/MVCCStrategy.java 2 ●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/NameStrategy.java 2 ●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java 242 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Example.java 6 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java
@@ -133,24 +133,27 @@
    @Override
    void toLDAP(final Context c, final JsonValue v, final ResultHandler<List<Attribute>> h) {
        if (v.isMap()) {
            List<Attribute> result = new ArrayList<Attribute>(v.size());
            for (Map.Entry<String, Object> field : v.asMap().entrySet()) {
            final List<Attribute> result = new ArrayList<Attribute>(v.size());
            for (final Map.Entry<String, Object> field : v.asMap().entrySet()) {
                if (!isIncludedAttribute(field.getKey())) {
                    continue;
                }
                final AttributeDescription ad;
                try {
                    ad = AttributeDescription.valueOf(field.getKey(), c.getConfig().schema());
                } catch (Exception e) {
                } catch (final Exception e) {
                    // FIXME: improve error message.
                    h.handleError(new BadRequestException("The field " + field.getKey()
                            + " is invalid"));
                    return;
                }
                Object value = field.getValue();
                final Object value = field.getValue();
                if (isJSONPrimitive(value)) {
                    result.add(Attributes.singletonAttribute(ad, value));
                } else if (value instanceof Collection<?>) {
                    Attribute a =
                    final Attribute a =
                            c.getConfig().decodeOptions().getAttributeFactory().newAttribute(ad);
                    for (Object o : (Collection<?>) value) {
                    for (final Object o : (Collection<?>) value) {
                        if (isJSONPrimitive(o)) {
                            a.add(o);
                        } else {
@@ -174,10 +177,6 @@
        }
    }
    private boolean isJSONPrimitive(Object value) {
        return value instanceof String || value instanceof Boolean || value instanceof Number;
    }
    private boolean isIncludedAttribute(final String name) {
        final String lowerName = toLowerCase(name);
@@ -193,4 +192,8 @@
        return false;
    }
    private boolean isJSONPrimitive(final Object value) {
        return value instanceof String || value instanceof Boolean || value instanceof Number;
    }
}
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/MVCCStrategy.java
@@ -24,7 +24,7 @@
 * A multi-version concurrency control strategy is responsible for ensuring that
 * clients can perform atomic updates to LDAP resources.
 */
public abstract class MVCCStrategy {
abstract class MVCCStrategy {
    /*
     * This interface is an abstract class so that methods can be made package
     * private until API is finalized.
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/NameStrategy.java
@@ -25,7 +25,7 @@
/**
 * A name strategy is responsible for naming REST resources and LDAP entries.
 */
public abstract class NameStrategy {
abstract class NameStrategy {
    /*
     * This interface is an abstract class so that methods can be made package
     * private until API is finalized.
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
@@ -54,70 +54,17 @@
    public static final class Builder {
        private DN baseDN; // TODO: support template variables.
        private ConnectionFactory factory;
        private final Filter falseFilter = Filter.present("1.1");
        private final List<AttributeMapper> mappers = new LinkedList<AttributeMapper>();
        private MVCCStrategy mvccStrategy = mvccUsingEtag();
        private NameStrategy nameStrategy = nameByEntryUUID("uid");
        private Filter falseFilter = Filter.present("1.1");
        private Schema schema = Schema.getDefaultSchema();
        private MVCCStrategy mvccStrategy;
        private NameStrategy nameStrategy;
        private ReadOnUpdatePolicy readOnUpdatePolicy = USE_READ_ENTRY_CONTROLS;
        private Schema schema = Schema.getDefaultSchema();
        private Filter trueFilter = Filter.objectClassPresent();
        Builder() {
            // No implementation required.
        }
        /**
         * Sets the schema which should be used when attribute types and
         * controls.
         *
         * @param schema
         *            The schema which should be used when attribute types and
         *            controls.
         * @return A reference to this builder.
         */
        public Builder schema(final Schema schema) {
            this.schema = ensureNotNull(schema);
            return this;
        }
        /**
         * Sets the absolute false filter which should be used when querying the
         * LDAP server.
         *
         * @param filter
         *            The absolute false filter.
         * @return A reference to this builder.
         */
        public Builder falseFilter(final Filter filter) {
            this.trueFilter = ensureNotNull(filter);
            return this;
        }
        /**
         * Sets the policy which should be used in order to read an entry before
         * it is deleted, or after it is added or modified.
         *
         * @param policy
         *            The policy which should be used in order to read an entry
         *            before it is deleted, or after it is added or modified.
         * @return A reference to this builder.
         */
        public Builder readOnUpdatePolicy(final ReadOnUpdatePolicy policy) {
            this.readOnUpdatePolicy = ensureNotNull(policy);
            return this;
        }
        /**
         * Sets the absolute true filter which should be used when querying the
         * LDAP server.
         *
         * @param filter
         *            The absolute true filter.
         * @return A reference to this builder.
         */
        public Builder trueFilter(final Filter filter) {
            this.trueFilter = ensureNotNull(filter);
            return this;
            useEtagAttribute();
            useServerEntryUUIDNaming("uid");
        }
        public Builder baseDN(final DN dn) {
@@ -149,6 +96,19 @@
            return this;
        }
        /**
         * Sets the absolute false filter which should be used when querying the
         * LDAP server.
         *
         * @param filter
         *            The absolute false filter.
         * @return A reference to this builder.
         */
        public Builder falseFilter(final Filter filter) {
            this.trueFilter = ensureNotNull(filter);
            return this;
        }
        public Builder map(final AttributeMapper... mappers) {
            ensureNotNull(mappers);
            this.mappers.addAll(Arrays.asList(mappers));
@@ -161,17 +121,99 @@
            return this;
        }
        public Builder with(final MVCCStrategy strategy) {
            ensureNotNull(strategy);
            this.mvccStrategy = strategy;
        /**
         * Sets the policy which should be used in order to read an entry before
         * it is deleted, or after it is added or modified.
         *
         * @param policy
         *            The policy which should be used in order to read an entry
         *            before it is deleted, or after it is added or modified.
         * @return A reference to this builder.
         */
        public Builder readOnUpdatePolicy(final ReadOnUpdatePolicy policy) {
            this.readOnUpdatePolicy = ensureNotNull(policy);
            return this;
        }
        public Builder with(final NameStrategy strategy) {
            ensureNotNull(strategy);
            this.nameStrategy = strategy;
        /**
         * Sets the schema which should be used when attribute types and
         * controls.
         *
         * @param schema
         *            The schema which should be used when attribute types and
         *            controls.
         * @return A reference to this builder.
         */
        public Builder schema(final Schema schema) {
            this.schema = ensureNotNull(schema);
            return this;
        }
        /**
         * Sets the absolute true filter which should be used when querying the
         * LDAP server.
         *
         * @param filter
         *            The absolute true filter.
         * @return A reference to this builder.
         */
        public Builder trueFilter(final Filter filter) {
            this.trueFilter = ensureNotNull(filter);
            return this;
        }
        public Builder useClientDNNaming(final AttributeType attribute) {
            this.nameStrategy = new DNNameStrategy(attribute);
            return this;
        }
        public Builder useClientDNNaming(final String attribute) {
            return useClientDNNaming(Schema.getDefaultSchema().getAttributeType(attribute));
        }
        public Builder useClientNaming(final AttributeType dnAttribute,
                final AttributeDescription idAttribute) {
            this.nameStrategy = new AttributeNameStrategy(dnAttribute, idAttribute, false);
            return this;
        }
        public Builder useClientNaming(final String dnAttribute, final String idAttribute) {
            return useClientNaming(Schema.getDefaultSchema().getAttributeType(dnAttribute),
                    AttributeDescription.valueOf(idAttribute));
        }
        public Builder useEtagAttribute() {
            return useEtagAttribute("etag");
        }
        public Builder useEtagAttribute(final AttributeDescription attribute) {
            this.mvccStrategy = new AttributeMVCCStrategy(attribute);
            return this;
        }
        public Builder useEtagAttribute(final String attribute) {
            return useEtagAttribute(AttributeDescription.valueOf(attribute));
        }
        public Builder useServerEntryUUIDNaming(final AttributeType dnAttribute) {
            return useServerNaming(dnAttribute, AttributeDescription
                    .create(getEntryUUIDAttributeType()));
        }
        public Builder useServerEntryUUIDNaming(final String dnAttribute) {
            return useServerEntryUUIDNaming(Schema.getDefaultSchema().getAttributeType(dnAttribute));
        }
        public Builder useServerNaming(final AttributeType dnAttribute,
                final AttributeDescription idAttribute) {
            this.nameStrategy = new AttributeNameStrategy(dnAttribute, idAttribute, true);
            return this;
        }
        public Builder useServerNaming(final String dnAttribute, final String idAttribute) {
            return useServerNaming(Schema.getDefaultSchema().getAttributeType(dnAttribute),
                    AttributeDescription.valueOf(idAttribute));
        }
    }
    private static final class AttributeMVCCStrategy extends MVCCStrategy {
@@ -182,13 +224,13 @@
        }
        @Override
        String getRevisionFromEntry(final Context c, final Entry entry) {
            return entry.parseAttribute(ldapAttribute).asString();
        void getLDAPAttributes(final Context c, final Set<String> ldapAttributes) {
            ldapAttributes.add(ldapAttribute.toString());
        }
        @Override
        void getLDAPAttributes(final Context c, final Set<String> ldapAttributes) {
            ldapAttributes.add(ldapAttribute.toString());
        String getRevisionFromEntry(final Context c, final Entry entry) {
            return entry.parseAttribute(ldapAttribute).asString();
        }
    }
@@ -272,6 +314,10 @@
    }
    public static Builder builder() {
        return new Builder();
    }
    public static SimpleAttributeMapper map(final AttributeDescription attribute) {
        return map(attribute.toString(), attribute);
    }
@@ -312,66 +358,14 @@
        return new JSONConstantAttributeMapper(attribute, attributeValue);
    }
    public static AttributeMapper mapLDAPConstant(final String attribute,
            final Object attributeValue) {
        return mapLDAPConstant(AttributeDescription.valueOf(attribute), attributeValue);
    }
    public static AttributeMapper mapLDAPConstant(final AttributeDescription attribute,
            final Object attributeValue) {
        return new LDAPConstantAttributeMapper(attribute, attributeValue);
    }
    public static MVCCStrategy mvccUsingAttribute(final AttributeDescription attribute) {
        return new AttributeMVCCStrategy(attribute);
    }
    public static MVCCStrategy mvccUsingAttribute(final String attribute) {
        return mvccUsingAttribute(AttributeDescription.valueOf(attribute));
    }
    public static MVCCStrategy mvccUsingEtag() {
        return mvccUsingAttribute("etag");
    }
    public static NameStrategy nameByClient(final AttributeType dnAttribute,
            final AttributeDescription idAttribute) {
        return new AttributeNameStrategy(dnAttribute, idAttribute, false);
    }
    public static NameStrategy nameByClient(final String dnAttribute, final String idAttribute) {
        return nameByClient(Schema.getDefaultSchema().getAttributeType(dnAttribute),
                AttributeDescription.valueOf(idAttribute));
    }
    public static NameStrategy nameByDN(final AttributeType attribute) {
        return new DNNameStrategy(attribute);
    }
    public static NameStrategy nameByDN(final String attribute) {
        return nameByDN(Schema.getDefaultSchema().getAttributeType(attribute));
    }
    public static NameStrategy nameByEntryUUID(final AttributeType dnAttribute) {
        return nameByServer(dnAttribute, AttributeDescription.create(getEntryUUIDAttributeType()));
    }
    public static NameStrategy nameByEntryUUID(final String dnAttribute) {
        return nameByEntryUUID(Schema.getDefaultSchema().getAttributeType(dnAttribute));
    }
    public static NameStrategy nameByServer(final AttributeType dnAttribute,
            final AttributeDescription idAttribute) {
        return new AttributeNameStrategy(dnAttribute, idAttribute, true);
    }
    public static NameStrategy nameByServer(final String dnAttribute, final String idAttribute) {
        return nameByServer(Schema.getDefaultSchema().getAttributeType(dnAttribute),
                AttributeDescription.valueOf(idAttribute));
    }
    public static Builder collection() {
        return new Builder();
    public static AttributeMapper mapLDAPConstant(final String attribute,
            final Object attributeValue) {
        return mapLDAPConstant(AttributeDescription.valueOf(attribute), attributeValue);
    }
    private static AttributeMapper mapOf(final Collection<AttributeMapper> mappers) {
opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Example.java
@@ -18,7 +18,7 @@
import static org.forgerock.json.resource.Resources.newInternalConnectionFactory;
import static org.forgerock.opendj.ldap.Connections.newAuthenticatedConnectionFactory;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.collection;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.builder;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.map;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.mapAllOf;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.mapComplex;
@@ -64,7 +64,7 @@
        // Create user resource.
        CollectionResourceProvider users =
                collection().factory(ldapFactory).baseDN("ou=people,dc=example,dc=com").map(
                builder().factory(ldapFactory).baseDN("ou=people,dc=example,dc=com").map(
                        map("id", "entryUUID").singleValued(true),
                        mapAllOf("uid", "isMemberOf", "modifyTimestamp"),
                        mapComplex("name", mapAllOf("cn", "sn", "givenName")),
@@ -75,7 +75,7 @@
        // Create group resource.
        CollectionResourceProvider groups =
                collection().factory(ldapFactory).baseDN("ou=groups,dc=example,dc=com").map(
                builder().factory(ldapFactory).baseDN("ou=groups,dc=example,dc=com").map(
                        mapAllOf("cn", "ou", "description", "uniquemember")).build();
        router.addRoute("/groups", groups);