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

Matthew Swift
23.39.2012 3860d5be4f50439c6e37af1aec7e352b4437491b
Add support for complex and simple JSON attribute mappings.
4 files modified
2 files added
370 ■■■■ changed files
opendj-sdk/opendj3/opendj-rest2ldap/pom.xml 2 ●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java 115 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java 20 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java 111 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java 13 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java 109 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj3/opendj-rest2ldap/pom.xml
@@ -61,7 +61,7 @@
        <dependency>
            <groupId>org.forgerock.commons</groupId>
            <artifactId>json-fluent</artifactId>
            <version>1.1.0</version>
            <version>1.2.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ComplexAttributeMapper.java
New file
@@ -0,0 +1,115 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyrighted [year] [name of copyright owner]".
 *
 * Copyright 2012 ForgeRock AS. All rights reserved.
 */
package org.forgerock.opendj.rest2ldap;
import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.json.fluent.JsonPointer;
import org.forgerock.json.fluent.JsonValue;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.resource.exception.ResourceException;
import org.forgerock.resource.provider.Context;
/**
 *
 */
public class ComplexAttributeMapper implements AttributeMapper {
    private final String normalizedJsonAttributeName;
    private final String jsonAttributeName;
    private final AttributeMapper mapper;
    /**
     * Creates a new complex attribute mapper which will wrap the results of the
     * provided mapper as a complex JSON object.
     *
     * @param jsonAttributeName
     *            The name of the complex attribute.
     * @param mapper
     *            The mapper which should be used to provide the contents of the
     *            complex attribute.
     */
    public ComplexAttributeMapper(String jsonAttributeName, AttributeMapper mapper) {
        this.jsonAttributeName = jsonAttributeName;
        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
        this.mapper = mapper;
    }
    /**
     * {@inheritDoc}
     */
    public void getLDAPAttributes(Set<String> ldapAttributes) {
        mapper.getLDAPAttributes(ldapAttributes);
    }
    /**
     * {@inheritDoc}
     */
    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
        if (resourceAttribute.size() > 0) {
            String rootName = resourceAttribute.get(0);
            if (toLowerCase(rootName).equals(normalizedJsonAttributeName)) {
                JsonPointer relativePointer = resourceAttribute.relativePointer();
                if (relativePointer == null) {
                    // User requested the entire contents of this complex
                    // attribute.
                    mapper.getLDAPAttributes(ldapAttributes);
                } else {
                    // User requested partial contents of this complex
                    // attribute.
                    mapper.getLDAPAttributes(ldapAttributes, relativePointer);
                }
            }
        }
    }
    /**
     * {@inheritDoc}
     */
    public void toJson(Context c, Entry e,
            final AttributeMapperCompletionHandler<Map<String, Object>> h) {
        AttributeMapperCompletionHandler<Map<String, Object>> wrapper =
                new AttributeMapperCompletionHandler<Map<String, Object>>() {
                    public void onSuccess(Map<String, Object> result) {
                        Map<String, Object> complexResult =
                                Collections.singletonMap(jsonAttributeName, (Object) result);
                        h.onSuccess(complexResult);
                    }
                    public void onFailure(ResourceException e) {
                        h.onFailure(e);
                    }
                };
        mapper.toJson(c, e, wrapper);
    }
    /**
     * {@inheritDoc}
     */
    public void toLDAP(Context c, JsonValue v, AttributeMapperCompletionHandler<List<Attribute>> h) {
        // TODO Auto-generated method stub
    }
}
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/CompositeAttributeMapper.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,22 +37,21 @@
 *
 */
public final class CompositeAttributeMapper implements AttributeMapper {
    private final Set<String> allLDAPAttributes;
    private final List<AttributeMapper> attributeMappers;
    private final Set<String> allLDAPAttributes = new LinkedHashSet<String>();
    private final List<AttributeMapper> attributeMappers = new LinkedList<AttributeMapper>();
    /**
     * Creates a new composite attribute mapper.
     *
     * @param attributeMappers
     *            The list of attribute mappers.
     */
    public CompositeAttributeMapper(final List<AttributeMapper> attributeMappers) {
        this.attributeMappers = new ArrayList<AttributeMapper>(attributeMappers);
        Set<String> tmp = new LinkedHashSet<String>(attributeMappers.size());
        for (final AttributeMapper mapper : attributeMappers) {
            mapper.getLDAPAttributes(tmp);
    public CompositeAttributeMapper() {
        // No implementation required.
        }
        allLDAPAttributes = Collections.unmodifiableSet(tmp);
    public CompositeAttributeMapper addMapper(AttributeMapper mapper) {
        attributeMappers.add(mapper);
        mapper.getLDAPAttributes(allLDAPAttributes);
        return this;
    }
    /**
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/DefaultAttributeMapper.java
New file
@@ -0,0 +1,111 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyrighted [year] [name of copyright owner]".
 *
 * Copyright 2012 ForgeRock AS. All rights reserved.
 */
package org.forgerock.opendj.rest2ldap;
import static org.forgerock.opendj.rest2ldap.Utils.attributeToJson;
import static org.forgerock.opendj.rest2ldap.Utils.getAttributeName;
import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.json.fluent.JsonPointer;
import org.forgerock.json.fluent.JsonValue;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.resource.provider.Context;
/**
 *
 */
public final class DefaultAttributeMapper implements AttributeMapper {
    // All user attributes by default.
    private final Map<String, String> includedAttributes = new LinkedHashMap<String, String>();
    private final Map<String, String> excludedAttributes = new LinkedHashMap<String, String>();
    public DefaultAttributeMapper() {
        // No implementation required.
    }
    public DefaultAttributeMapper includeAttribute(String... attributes) {
        for (String attribute : attributes) {
            includedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    }
    public DefaultAttributeMapper excludeAttribute(String... attributes) {
        for (String attribute : attributes) {
            excludedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    }
    public void getLDAPAttributes(Set<String> ldapAttributes) {
        if (!includedAttributes.isEmpty()) {
            ldapAttributes.addAll(includedAttributes.values());
        } else {
            // All user attributes.
            ldapAttributes.add("*");
        }
    }
    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
        String name = resourceAttribute.leaf();
        if (name != null) {
            if (isIncludedAttribute(name)) {
                ldapAttributes.add(name);
            } else {
                // FIXME: log something or return a ResourceException?
            }
        }
    }
    public void toJson(Context c, Entry e, AttributeMapperCompletionHandler<Map<String, Object>> h) {
        Map<String, Object> result = new LinkedHashMap<String, Object>(e.getAttributeCount());
        for (Attribute a : e.getAllAttributes()) {
            String name = getAttributeName(a);
            if (isIncludedAttribute(name)) {
                result.put(name, attributeToJson(a));
            }
        }
        h.onSuccess(result);
    }
    private boolean isIncludedAttribute(String name) {
        String lowerName = toLowerCase(name);
        // Ignore the requested attribute if it has been excluded.
        if (excludedAttributes.containsKey(lowerName)) {
            return false;
        }
        // Include all attributes by default.
        if (includedAttributes.isEmpty() || includedAttributes.containsKey(lowerName)) {
            return true;
        }
        return false;
    }
    public void toLDAP(Context c, JsonValue v, AttributeMapperCompletionHandler<List<Attribute>> h) {
        // TODO:
    }
}
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Example.java
@@ -61,8 +61,15 @@
        // Create user resource.
        AttributeMapper userMapper =
                new SimpleAttributeMapper().includeAttribute("uid", "cn", "sn", "mail",
                        "isMemberOf", "modifyTimestamp");
                new CompositeAttributeMapper().addMapper(
                        new DefaultAttributeMapper().includeAttribute("uid", "isMemberOf",
                                "modifyTimestamp")).addMapper(
                        new ComplexAttributeMapper("name", new DefaultAttributeMapper()
                                .includeAttribute("cn", "sn", "givenName"))).addMapper(
                        new ComplexAttributeMapper("contactInformation",
                                new CompositeAttributeMapper().addMapper(
                                        new SimpleAttributeMapper("telephoneNumber")).addMapper(
                                        new SimpleAttributeMapper("emailAddress", "mail"))));
        LDAPResource userResource = new LDAPResource(userContainer, userMapper);
        ResourceInvoker userResourceInvoker = new ResourceInvoker();
        userResourceInvoker.resource = userResource; // FIXME: Yuk!
@@ -70,7 +77,7 @@
        // Create group resource.
        AttributeMapper groupMapper =
                new SimpleAttributeMapper().includeAttribute("cn", "ou", "description",
                new DefaultAttributeMapper().includeAttribute("cn", "ou", "description",
                        "uniquemember");
        LDAPResource groupResource = new LDAPResource(groupContainer, groupMapper);
        ResourceInvoker groupResourceInvoker = new ResourceInvoker();
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
@@ -16,10 +16,10 @@
package org.forgerock.opendj.rest2ldap;
import static org.forgerock.opendj.rest2ldap.Utils.getAttributeName;
import static org.forgerock.opendj.rest2ldap.Utils.attributeToJson;
import static org.forgerock.opendj.rest2ldap.Utils.toLowerCase;
import java.util.LinkedHashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -33,78 +33,73 @@
/**
 *
 */
public final class SimpleAttributeMapper implements AttributeMapper {
public class SimpleAttributeMapper implements AttributeMapper {
    // All user attributes by default.
    private final Map<String, String> includedAttributes = new LinkedHashMap<String, String>();
    private final Map<String, String> excludedAttributes = new LinkedHashMap<String, String>();
    private final String ldapAttributeName;
    private final String jsonAttributeName;
    private final String normalizedJsonAttributeName;
    public SimpleAttributeMapper() {
        // No implementation required.
    /**
     * Creates a new simple attribute mapper which maps a single LDAP attribute
     * to an entry.
     *
     * @param attributeName
     *            The name of the simple JSON and LDAP attribute.
     */
    public SimpleAttributeMapper(String attributeName) {
        this(attributeName, attributeName);
    }
    public SimpleAttributeMapper includeAttribute(String... attributes) {
        for (String attribute : attributes) {
            includedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    /**
     * Creates a new simple attribute mapper which maps a single LDAP attribute
     * to an entry.
     *
     * @param jsonAttributeName
     *            The name of the simple JSON attribute.
     * @param ldapAttributeName
     *            The name of the LDAP attribute.
     */
    public SimpleAttributeMapper(String jsonAttributeName, String ldapAttributeName) {
        this.jsonAttributeName = jsonAttributeName;
        this.normalizedJsonAttributeName = toLowerCase(jsonAttributeName);
        this.ldapAttributeName = ldapAttributeName;
    }
    public SimpleAttributeMapper excludeAttribute(String... attributes) {
        for (String attribute : attributes) {
            excludedAttributes.put(toLowerCase(attribute), attribute);
        }
        return this;
    }
    /**
     * {@inheritDoc}
     */
    public void getLDAPAttributes(Set<String> ldapAttributes) {
        if (!includedAttributes.isEmpty()) {
            ldapAttributes.addAll(includedAttributes.values());
        } else {
            // All user attributes.
            ldapAttributes.add("*");
        }
        ldapAttributes.add(ldapAttributeName);
    }
    /**
     * {@inheritDoc}
     */
    public void getLDAPAttributes(Set<String> ldapAttributes, JsonPointer resourceAttribute) {
        String name = resourceAttribute.leaf();
        if (name != null) {
            if (isIncludedAttribute(name)) {
                ldapAttributes.add(name);
            } else {
                // FIXME: log something or return a ResourceException?
            }
        if (toLowerCase(resourceAttribute.leaf()).equals(normalizedJsonAttributeName)) {
            ldapAttributes.add(ldapAttributeName);
        }
    }
    public void toJson(Context c, Entry e, AttributeMapperCompletionHandler<Map<String, Object>> h) {
        Map<String, Object> result = new LinkedHashMap<String, Object>(e.getAttributeCount());
        for (Attribute a : e.getAllAttributes()) {
            String name = getAttributeName(a);
            if (isIncludedAttribute(name)) {
                result.put(name, Utils.attributeToJson(a));
            }
        }
    /**
     * {@inheritDoc}
     */
    public void toJson(Context c, Entry e,
            final AttributeMapperCompletionHandler<Map<String, Object>> h) {
        Attribute a = e.getAttribute(ldapAttributeName);
        if (a != null) {
            Map<String, Object> result =
                    Collections.singletonMap(jsonAttributeName, attributeToJson(a));
        h.onSuccess(result);
    }
    private boolean isIncludedAttribute(String name) {
        String lowerName = toLowerCase(name);
        // Ignore the requested attribute if it has been excluded.
        if (excludedAttributes.containsKey(lowerName)) {
            return false;
        }
        // Include all attributes by default.
        if (includedAttributes.isEmpty() || includedAttributes.containsKey(lowerName)) {
            return true;
        }
        return false;
    }
    /**
     * {@inheritDoc}
     */
    public void toLDAP(Context c, JsonValue v, AttributeMapperCompletionHandler<List<Attribute>> h) {
        // TODO:
        // TODO Auto-generated method stub
    }
}