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

Matthew Swift
22.27.2013 97aafc7c83ab91e2d3647699b15db7f3b6a29bef
Fix OPENDJ-757: Add Rest2LDAP gateway Servlet

1 files deleted
5 files added
3 files modified
525 ■■■■ changed files
opendj3/opendj-rest2ldap-servlet/pom.xml 107 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java 143 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/package-info.java 20 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/web.xml 29 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json 55 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/pom.xml 4 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java 46 ●●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Example.java 118 ●●●●● patch | view | raw | blame | history
opendj3/pom.xml 3 ●●●● patch | view | raw | blame | history
opendj3/opendj-rest2ldap-servlet/pom.xml
New file
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
  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 Copyright [year] [name of copyright owner]".
  Copyright 2013 ForgeRock AS.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>opendj-project</artifactId>
        <groupId>org.forgerock.opendj</groupId>
        <version>3.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>opendj-rest2ldap-servlet</artifactId>
    <name>OpenDJ Commons REST LDAP Gateway</name>
    <description>
        Provides integration between the OpenDJ Commons REST Adapter and Servlet APIs.
    </description>
    <packaging>bundle</packaging>
    <properties>
        <forgerockRestVersion>2.0.0-SNAPSHOT</forgerockRestVersion>
        <jacksonVersion>1.9.2</jacksonVersion>
        <checkstyleHeaderLocation>org/forgerock/checkstyle/default-java-header</checkstyleHeaderLocation>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.forgerock.opendj</groupId>
            <artifactId>opendj-rest2ldap</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.forgerock.commons</groupId>
            <artifactId>json-resource-servlet</artifactId>
            <version>${forgerockRestVersion}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>${jacksonVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>${jacksonVersion}</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Export-Package>
                            org.forgerock.opendj.rest2ldap.servlet;version=${project.version}
                        </Export-Package>
                    </instructions>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <executions>
                    <execution>
                        <id>war</id>
                        <phase>package</phase>
                        <goals>
                            <goal>war</goal>
                        </goals>
                        <configuration>
                            <classifier>servlet</classifier>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>8.1.7.v20120910</version>
            </plugin>
        </plugins>
    </build>
</project>
opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
New file
@@ -0,0 +1,143 @@
/*
 * 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 copyright [year] [name of copyright owner]".
 *
 * Copyright 2013 ForgeRock AS.
 */
package org.forgerock.opendj.rest2ldap.servlet;
import java.io.InputStream;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.codehaus.jackson.map.ObjectMapper;
import org.forgerock.json.fluent.JsonValue;
import org.forgerock.json.resource.CollectionResourceProvider;
import org.forgerock.json.resource.ConnectionFactory;
import org.forgerock.json.resource.Resources;
import org.forgerock.json.resource.Router;
import org.forgerock.opendj.rest2ldap.Rest2LDAP;
import org.forgerock.opendj.rest2ldap.Rest2LDAP.Builder;
/**
 * The connection factory provider which is used by the OpenDJ Commons REST LDAP
 * Gateway.
 */
public final class Rest2LDAPConnectionFactoryProvider {
    private static final String INIT_PARAM_CONFIG_FILE = "config-file";
    private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
    /**
     * Returns a JSON resource connection factory configured using the
     * configuration file named in the {@code config-file} Servlet
     * initialization parameter. The configuration file should have the
     * following JSON structure excluding the C-like comments:
     *
     * <pre>
     * {
     *     // The LDAP server configuration - see Rest2LDAP.configureConnectionFactory(JsonValue).
     *     "primaryLDAPServers" : [
     *         {
     *             "hostname" : "host1.example.com",
     *             "port"     : 389
     *         }
     *     ],
     *
     *     ...
     *
     *     // The LDAP mappings
     *     "mappings" : {
     *         "/users" : {
     *             // The LDAP mapping for /users - Rest2LDAP.Builder.configureMapping(JsonValue).
     *             "baseDN" : "ou=people,dc=example,dc=com",
     *
     *             ...
     *         },
     *         "/groups" : {
     *             // The LDAP mapping for /groups - Rest2LDAP.Builder.configureMapping(JsonValue).
     *             "baseDN" : "ou=groups,dc=example,dc=com",
     *
     *             ...
     *         }
     *     }
     * }
     * </pre>
     *
     * @param config
     *            The Servlet configuration.
     * @return The configured JSON resource connection factory.
     * @throws ServletException
     *             If the connection factory could not be initialized.
     * @see Rest2LDAP#configureConnectionFactory(JsonValue)
     * @see Builder#configureMapping(JsonValue)
     */
    public static ConnectionFactory getConnectionFactory(final ServletConfig config)
            throws ServletException {
        final String configFileName = config.getInitParameter(INIT_PARAM_CONFIG_FILE);
        if (configFileName == null) {
            throw new ServletException("Servlet initialization parameter '"
                    + INIT_PARAM_CONFIG_FILE + "' not specified");
        }
        final InputStream configFile =
                config.getServletContext().getResourceAsStream(configFileName);
        if (configFile == null) {
            throw new ServletException("Servlet configuration file '" + configFileName
                    + "' not found");
        }
        try {
            // Parse the config file.
            final Object content = JSON_MAPPER.readValue(configFile, Object.class);
            if (!(content instanceof Map)) {
                throw new ServletException("Servlet configuration file '" + configFileName
                        + "' does not contain a valid JSON configuration");
            }
            final JsonValue configuration = new JsonValue(content);
            // Parse the LDAP connection configuration.
            final org.forgerock.opendj.ldap.ConnectionFactory ldapFactory =
                    Rest2LDAP.configureConnectionFactory(configuration);
            // Create the router.
            final Router router = new Router();
            final JsonValue mappings = configuration.get("mappings").required();
            for (final String mappingUrl : mappings.keys()) {
                final JsonValue mapping = mappings.get(mappingUrl);
                final CollectionResourceProvider provider =
                        Rest2LDAP.builder().connectionFactory(ldapFactory)
                                .configureMapping(mapping).build();
                router.addRoute(mappingUrl, provider);
            }
            return Resources.newInternalConnectionFactory(router);
        } catch (final ServletException e) {
            // Rethrow.
            throw e;
        } catch (final Exception e) {
            throw new ServletException("Servlet configuration file '" + configFileName
                    + "' could not be read: " + e.getMessage());
        } finally {
            try {
                configFile.close();
            } catch (final Exception e) {
                // Ignore.
            }
        }
    }
    // Prevent instantiation.
    private Rest2LDAPConnectionFactoryProvider() {
        // Nothing to do.
    }
}
opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/package-info.java
New file
@@ -0,0 +1,20 @@
/*
 * 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 copyright [year] [name of copyright owner]".
 *
 * Copyright 2013 ForgeRock AS.
 */
/**
 * Provides integration between the OpenDJ Commons REST Adapter and Servlet APIs.
 */
package org.forgerock.opendj.rest2ldap.servlet;
opendj3/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/web.xml
New file
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <display-name>Json Resource Servlet</display-name>
    <servlet>
        <servlet-name>OpenDJ Commons REST LDAP Gateway</servlet-name>
        <servlet-class>org.forgerock.json.resource.servlet.HttpServlet</servlet-class>
        <init-param>
            <param-name>connection-factory-class</param-name>
            <param-value>org.forgerock.opendj.rest2ldap.servlet.Rest2LDAPConnectionFactoryProvider</param-value>
        </init-param>
        <init-param>
            <param-name>config-file</param-name>
            <param-value>/opendj-rest2ldap-servlet.json</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>OpenDJ Commons REST LDAP Gateway</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>
opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
New file
@@ -0,0 +1,55 @@
{
    "primaryLDAPServers" : [
        {
            "hostname" : "localhost",
            "port"     : 1389
        }
    ],
    "authentication" : {
        "bindDN"   : "cn=directory manager",
        "password" : "password"
    },
    "connectionPoolSize"       : 10,
    "heartBeatIntervalSeconds" : 30,
    "mappings" : {
        "/users" : {
            "baseDN" : "ou=people,dc=example,dc=com",
            "readOnUpdatePolicy" : "controls",
            "additionalLDAPAttributes" : [
                {
                    "type" : "objectClass",
                    "values" : [
                        "top",
                        "person",
                        "organizationalPerson",
                        "inetOrgPerson"
                    ]
                }
            ],
            "namingStrategy" : {
                "strategy" : "clientDNNaming",
                "dnAttribute" : "uid"
            },
            "etagAttribute" : "etag",
            "attributes" : {
                "schemas"     : { "constant" : [ "urn:scim:schemas:core:1.0" ] },
                "id"          : { "simple"   : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true, "writability" : "createOnly" } },
                "rev"         : { "simple"   : { "ldapAttribute" : "etag", "isSingleValued" : true, "writability" : "readOnly" } },
                "userName"    : { "simple"   : { "ldapAttribute" : "mail", "isSingleValued" : true, "writability" : "readOnly" } },
                "displayName" : { "simple"   : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true } },
                "name" : { "object"   : {
                    "givenName"  : { "simple" : { "ldapAttribute" : "givenName", "isSingleValued" : true } },
                    "familyName" : { "simple" : { "ldapAttribute" : "sn", "isSingleValued" : true, "isRequired" : true } }
                } },
                "contactInformation" : { "object"   : {
                    "telephoneNumber" : { "simple" : { "ldapAttribute" : "telephoneNumber", "isSingleValued" : true } },
                    "emailAddress"    : { "simple" : { "ldapAttribute" : "mail", "isSingleValued" : true } }
                } }
            }
        }
    }
}
opendj3/opendj-rest2ldap/pom.xml
@@ -23,9 +23,9 @@
        <version>3.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>opendj-rest2ldap</artifactId>
    <name>OpenDJ REST to LDAP Gateway</name>
    <name>OpenDJ Commons REST Adapter</name>
    <description>
        This module includes APIs for implementing REST to LDAP gateways.
        This module includes APIs for accessing LDAP repositories using commons REST.
    </description>
    <packaging>jar</packaging>
    <properties>
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
@@ -47,6 +47,8 @@
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.RoundRobinLoadBalancingAlgorithm;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.requests.BindRequest;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.Schema;
@@ -117,8 +119,7 @@
         * @throws IllegalArgumentException
         *             If the configuration is invalid.
         */
        public Builder configureConnectionFactory(final JsonValue configuration)
                throws IllegalArgumentException {
        public Builder configureConnectionFactory(final JsonValue configuration) {
            connectionFactory(Rest2LDAP.configureConnectionFactory(configuration));
            return this;
        }
@@ -192,8 +193,7 @@
         * @throws IllegalArgumentException
         *             If the configuration is invalid.
         */
        public Builder configureMapping(final JsonValue configuration)
                throws IllegalArgumentException {
        public Builder configureMapping(final JsonValue configuration) {
            baseDN(configuration.get("baseDN").required().asString());
            final JsonValue readOnUpdatePolicy = configuration.get("readOnUpdatePolicy");
@@ -545,9 +545,10 @@
     *         ...
     *     },
     *
     *     // Authentication configuration (mandatory and TBD).
     *     // Authentication configuration (optional and TBD).
     *     "authentication" : {
     *         ...
     *         "bindDN"   : "cn=directory manager",
     *         "password" : "password"
     *     },
     * }
     * </pre>
@@ -558,32 +559,41 @@
     * @throws IllegalArgumentException
     *             If the configuration is invalid.
     */
    public static ConnectionFactory configureConnectionFactory(final JsonValue configuration)
            throws IllegalArgumentException {
    public static ConnectionFactory configureConnectionFactory(final JsonValue configuration) {
        // Parse pool parameters,
        final int connectionPoolSize =
                Math.max(configuration.get("connectionPoolSize").defaultTo(10).asInteger(), 1);
        final int heartBeatIntervalSeconds =
                Math.max(configuration.get("heartBeatIntervalSeconds").defaultTo(30).asInteger(), 1);
        // Parse authentication parameters.
        final BindRequest bindRequest;
        if (configuration.isDefined("authentication")) {
            final JsonValue authn = configuration.get("authentication");
            bindRequest =
                    Requests.newSimpleBindRequest(authn.get("bindDN").required().asString(), authn
                            .get("password").required().asString().toCharArray());
        } else {
            bindRequest = null;
        }
        // Parse primary data center.
        final JsonValue primaryLDAPServers = configuration.get("primaryLDAPServers");
        if (primaryLDAPServers == null || !primaryLDAPServers.isList()
                || primaryLDAPServers.size() == 0) {
        if (!primaryLDAPServers.isList() || primaryLDAPServers.size() == 0) {
            throw new IllegalArgumentException("No primaryLDAPServers");
        }
        final ConnectionFactory primary =
                parseLDAPServers(primaryLDAPServers, connectionPoolSize, heartBeatIntervalSeconds);
                parseLDAPServers(primaryLDAPServers, bindRequest, connectionPoolSize,
                        heartBeatIntervalSeconds);
        // Parse secondary data center(s).
        final JsonValue secondaryLDAPServers = configuration.get("secondaryLDAPServers");
        final ConnectionFactory secondary;
        if (secondaryLDAPServers != null && secondaryLDAPServers.isList()
                && secondaryLDAPServers.size() != 0) {
        if (secondaryLDAPServers.isList() && secondaryLDAPServers.size() != 0) {
            secondary =
                    parseLDAPServers(secondaryLDAPServers, connectionPoolSize,
                    parseLDAPServers(secondaryLDAPServers, bindRequest, connectionPoolSize,
                            heartBeatIntervalSeconds);
        } else if (secondaryLDAPServers != null && !secondaryLDAPServers.isList()) {
        } else if (!secondaryLDAPServers.isNull()) {
            throw new IllegalArgumentException("Invalid secondaryLDAPServers configuration");
        } else {
            secondary = null;
@@ -615,12 +625,16 @@
    }
    private static ConnectionFactory parseLDAPServers(final JsonValue config,
            final int connectionPoolSize, final int heartBeatIntervalSeconds) {
            final BindRequest bindRequest, final int connectionPoolSize,
            final int heartBeatIntervalSeconds) {
        final List<ConnectionFactory> servers = new ArrayList<ConnectionFactory>(config.size());
        for (final JsonValue server : config) {
            final String host = server.get("hostname").required().asString();
            final int port = server.get("port").required().asInteger();
            ConnectionFactory factory = new LDAPConnectionFactory(host, port);
            if (bindRequest != null) {
                factory = Connections.newAuthenticatedConnectionFactory(factory, bindRequest);
            }
            if (connectionPoolSize > 1) {
                factory =
                        Connections.newHeartBeatConnectionFactory(factory,
opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/Example.java
File was deleted
opendj3/pom.xml
@@ -91,8 +91,9 @@
  <modules>
    <module>opendj-ldap-sdk</module>
    <module>opendj-ldap-toolkit</module>
    <module>opendj-rest2ldap</module>
    <module>opendj-ldap-sdk-examples</module>
    <module>opendj-rest2ldap</module>
    <module>opendj-rest2ldap-servlet</module>
    <module>opendj-server2x-adapter</module>
  </modules>
  <properties>