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

Chris Ridd
23.13.2014 e60baaef11af6bcd6e7aee73b9e304732bf9a16e
Backport fix for OPENDJ-1466: Improve initialization of InetSocketAddress in SDK to prevent cached DNS data.
3 files modified
144 ■■■■ changed files
opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java 51 ●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java 8 ●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java 85 ●●●●● patch | view | raw | blame | history
opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
@@ -211,8 +211,8 @@
                return timeoutEndTime - currentTime;
            } else {
                future.handleErrorResult(newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
                        LDAP_CONNECTION_CONNECT_TIMEOUT.get(socketAddress.toString(), getTimeout())
                                .toString()));
                        LDAP_CONNECTION_CONNECT_TIMEOUT.get(getSocketAddress().toString(),
                                getTimeout()).toString()));
                return 0;
            }
        }
@@ -227,6 +227,8 @@
    private final FilterChain defaultFilterChain;
    private final LDAPOptions options;
    private final InetSocketAddress socketAddress;
    private final String host;
    private final int port;
    /**
     * Prevents the transport and timeoutChecker being released when there are
@@ -246,8 +248,8 @@
    /**
     * Creates a new LDAP connection factory implementation which can be used to
     * create connections to the Directory Server at the provided host and port
     * address using provided connection options.
     * create connections to the Directory Server at the provided address using
     * provided connection options.
     *
     * @param address
     *            The address of the Directory Server to connect to.
@@ -257,6 +259,8 @@
    public LDAPConnectionFactoryImpl(final InetSocketAddress address, final LDAPOptions options) {
        this.transport = DEFAULT_TRANSPORT.acquireIfNull(options.getTCPNIOTransport());
        this.socketAddress = address;
        this.host = null;
        this.port = -1;
        this.options = new LDAPOptions(options);
        this.clientFilter =
                new LDAPClientFilter(new LDAPReader(this.options.getDecodeOptions()), 0);
@@ -264,6 +268,30 @@
                FilterChainBuilder.stateless().add(new TransportFilter()).add(clientFilter).build();
    }
    /**
     * Creates a new LDAP connection factory implementation which can be used to
     * create connections to the Directory Server at the provided host and port
     * number using provided connection options.
     *
     * @param host
     *            The host name of the Directory Server to connect to.
     * @param port
     *            The port number of the Directory Server to connect to.
     * @param options
     *            The LDAP connection options to use when creating connections.
     */
    public LDAPConnectionFactoryImpl(final String host, final int port, final LDAPOptions options) {
        this.transport = DEFAULT_TRANSPORT.acquireIfNull(options.getTCPNIOTransport());
        this.socketAddress = null;
        this.host = host;
        this.port = port;
        this.options = new LDAPOptions(options);
        this.clientFilter =
              new LDAPClientFilter(new LDAPReader(this.options.getDecodeOptions()), 0);
        this.defaultFilterChain =
              FilterChainBuilder.stateless().add(new TransportFilter()).add(clientFilter).build();
    }
    @Override
    public void close() {
        if (isClosed.compareAndSet(false, true)) {
@@ -289,7 +317,7 @@
                        .build();
        final AsynchronousFutureResult<Connection, ResultHandler<? super Connection>> future =
                new AsynchronousFutureResult<Connection, ResultHandler<? super Connection>>(handler);
        connectorHandler.connect(socketAddress, new CompletionHandlerAdapter(future));
        connectorHandler.connect(getSocketAddress(), new CompletionHandlerAdapter(future));
        return future;
    }
@@ -299,14 +327,23 @@
     * @return The address of the Directory Server.
     */
    public InetSocketAddress getSocketAddress() {
        return socketAddress;
        if (socketAddress != null) {
            return socketAddress;
        }
        return new InetSocketAddress(host, port);
    }
    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("LDAPConnectionFactory(");
        builder.append(getSocketAddress().toString());
        if (socketAddress != null) {
            builder.append(socketAddress.toString());
        } else {
            builder.append(host);
            builder.append(':');
            builder.append(port);
        }
        builder.append(')');
        return builder.toString();
    }
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
@@ -86,7 +86,9 @@
     *            The address of the Directory Server.
     * @throws NullPointerException
     *             If {@code address} was {@code null}.
     * @deprecated use {@link #LDAPConnectionFactory(String, int)} instead.
     */
    @Deprecated
    public LDAPConnectionFactory(final InetSocketAddress address) {
        this(address, new LDAPOptions());
    }
@@ -101,7 +103,10 @@
     *            The LDAP options to use when creating connections.
     * @throws NullPointerException
     *             If {@code address} or {@code options} was {@code null}.
     * @deprecated use {@link #LDAPConnectionFactory(String, int,
     * org.forgerock.opendj.ldap.LDAPOptions)} instead.
     */
    @Deprecated
    public LDAPConnectionFactory(final InetSocketAddress address, final LDAPOptions options) {
        Validator.ensureNotNull(address, options);
        this.impl = new LDAPConnectionFactoryImpl(address, options);
@@ -139,8 +144,7 @@
     */
    public LDAPConnectionFactory(final String host, final int port, final LDAPOptions options) {
        Validator.ensureNotNull(host, options);
        final InetSocketAddress address = new InetSocketAddress(host, port);
        this.impl = new LDAPConnectionFactoryImpl(address, options);
        this.impl = new LDAPConnectionFactoryImpl(host, port, options);
    }
    /**
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2010 Sun Microsystems, Inc.
 *      Portions copyright 2011-2013 ForgeRock AS
 *      Portions copyright 2011-2014 ForgeRock AS
 */
package org.forgerock.opendj.ldap;
@@ -43,6 +43,8 @@
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -133,7 +135,7 @@
    @DataProvider
    Object[][] connectionFactories() throws Exception {
        Object[][] factories = new Object[21][1];
        Object[][] factories = new Object[27][1];
        // HeartBeatConnectionFactory
        // Use custom search request.
@@ -141,26 +143,45 @@
                Requests.newSearchRequest("uid=user.0,ou=people,o=test", SearchScope.BASE_OBJECT,
                        "objectclass=*", "cn");
        SocketAddress addr = getServerSocketAddress();
        assertTrue(addr instanceof InetSocketAddress);
        InetSocketAddress socketAddress = (InetSocketAddress) addr;
        factories[0][0] =
                Connections.newHeartBeatConnectionFactory(new LDAPConnectionFactory(
                        getServerSocketAddress()), 1000, 500, TimeUnit.MILLISECONDS, request);
                        socketAddress), 1000, 500, TimeUnit.MILLISECONDS, request);
        factories[1][0] =
                Connections.newHeartBeatConnectionFactory(new LDAPConnectionFactory(
                        socketAddress.getHostName(), socketAddress.getPort()), 1000, 500,
                        TimeUnit.MILLISECONDS, request);
        // InternalConnectionFactory
        factories[1][0] = Connections.newInternalConnectionFactory(LDAPServer.getInstance(), null);
        factories[2][0] = Connections.newInternalConnectionFactory(LDAPServer.getInstance(), null);
        // AuthenticatedConnectionFactory
        factories[2][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        getServerSocketAddress()), Requests.newSimpleBindRequest("", new char[0]));
        // AuthenticatedConnectionFactory with multi-stage SASL
        factories[3][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        getServerSocketAddress()), Requests.newCRAMMD5SASLBindRequest("id:user",
                        socketAddress), Requests.newSimpleBindRequest("", new char[0]));
        factories[4][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        socketAddress.getHostName(), socketAddress.getPort()),
                        Requests.newSimpleBindRequest("", new char[0]));
        // AuthenticatedConnectionFactory with multi-stage SASL
        factories[5][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        socketAddress), Requests.newCRAMMD5SASLBindRequest("id:user",
                            "password".toCharArray()));
        factories[6][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        socketAddress.getHostName(), socketAddress.getPort()),
                        Requests.newCRAMMD5SASLBindRequest("id:user",
                            "password".toCharArray()));
        // LDAPConnectionFactory with default options
        factories[4][0] = new LDAPConnectionFactory(getServerSocketAddress());
        factories[7][0] = new LDAPConnectionFactory(socketAddress);
        factories[8][0] = new LDAPConnectionFactory(socketAddress.getHostName(),
                socketAddress.getPort());
        // LDAPConnectionFactory with startTLS
        SSLContext sslContext =
@@ -174,16 +195,24 @@
                                    "SSL_DH_anon_WITH_DES_CBC_SHA", "SSL_DH_anon_WITH_RC4_128_MD5",
                                    "TLS_DH_anon_WITH_AES_128_CBC_SHA",
                                    "TLS_DH_anon_WITH_AES_256_CBC_SHA" });
        factories[5][0] = new LDAPConnectionFactory(getServerSocketAddress(), options);
        factories[9][0] = new LDAPConnectionFactory(socketAddress, options);
        factories[10][0] = new LDAPConnectionFactory(socketAddress.getHostName(),
                socketAddress.getPort(), options);
        // startTLS + SASL confidentiality
        // Use IP address here so that DIGEST-MD5 host verification works if
        // local host name is not localhost (e.g. on some machines it might be
        // localhost.localdomain).
        // FIXME: enable QOP once OPENDJ-514 is fixed.
        factories[6][0] =
        factories[11][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        getServerSocketAddress(), options), Requests.newDigestMD5SASLBindRequest(
                        socketAddress, options), Requests.newDigestMD5SASLBindRequest(
                            "id:user", "password".toCharArray()).setCipher(
                                DigestMD5SASLBindRequest.CIPHER_LOW));
        factories[12][0] =
                new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
                        socketAddress.getHostName(), socketAddress.getPort(), options),
                        Requests.newDigestMD5SASLBindRequest(
                            "id:user", "password".toCharArray()).setCipher(
                                DigestMD5SASLBindRequest.CIPHER_LOW));
@@ -197,45 +226,45 @@
                        getServerSocketAddress()), "online");
        // Connection pools.
        factories[7][0] = Connections.newFixedConnectionPool(onlineServer, 10);
        factories[13][0] = Connections.newFixedConnectionPool(onlineServer, 10);
        // Round robin.
        factories[8][0] =
        factories[14][0] =
                Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
                        onlineServer, offlineServer1)));
        factories[9][0] = factories[8][0];
        factories[10][0] = factories[8][0];
        factories[11][0] =
        factories[15][0] = factories[14][0];
        factories[16][0] = factories[14][0];
        factories[17][0] =
                Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
                        offlineServer1, onlineServer)));
        factories[12][0] =
        factories[18][0] =
                Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
                        offlineServer1, offlineServer2, onlineServer)));
        factories[13][0] =
        factories[19][0] =
                Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays
                        .<ConnectionFactory> asList(Connections.newFixedConnectionPool(
                                offlineServer1, 10), Connections.newFixedConnectionPool(
                                onlineServer, 10))));
        // Fail-over.
        factories[14][0] =
        factories[20][0] =
                Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
                        onlineServer, offlineServer1)));
        factories[15][0] = factories[14][0];
        factories[16][0] = factories[14][0];
        factories[17][0] =
        factories[21][0] = factories[20][0];
        factories[22][0] = factories[20][0];
        factories[23][0] =
                Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
                        offlineServer1, onlineServer)));
        factories[18][0] =
        factories[24][0] =
                Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
                        offlineServer1, offlineServer2, onlineServer)));
        factories[19][0] =
        factories[25][0] =
                Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays
                        .<ConnectionFactory> asList(Connections.newFixedConnectionPool(
                                offlineServer1, 10), Connections.newFixedConnectionPool(
                                onlineServer, 10))));
        factories[20][0] = Connections.newFixedConnectionPool(onlineServer, 10);
        factories[26][0] = Connections.newFixedConnectionPool(onlineServer, 10);
        return factories;
    }