From ed08a89377a333c10202ead88d355e16bcb3a0fd Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 27 Feb 2014 23:31:10 +0000
Subject: [PATCH] Backport fix for OPENDJ-1197: API is lacking functionality to specify TCP connect timeout

---
 opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java |  297 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 155 insertions(+), 142 deletions(-)

diff --git a/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java b/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
index 4a8e8fc..f34c0a5 100644
--- a/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
+++ b/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPOptions.java
@@ -22,11 +22,13 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions copyright 2012 ForgeRock AS.
+ *      Portions copyright 2012-2014 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldap;
 
+import static com.forgerock.opendj.util.Validator.ensureNotNull;
+
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -35,8 +37,6 @@
 
 import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
 
-import com.forgerock.opendj.util.Validator;
-
 /**
  * Common options for LDAP client connections.
  * <p>
@@ -56,25 +56,28 @@
  * // Connection uses StartTLS...
  * </pre>
  */
-public final class LDAPOptions {
+public final class LDAPOptions extends CommonLDAPOptions<LDAPOptions> {
+    // Default values for options taken from Java properties.
+    private static final long DEFAULT_TIMEOUT;
+    private static final long DEFAULT_CONNECT_TIMEOUT;
+    static {
+        DEFAULT_TIMEOUT = getIntProperty("org.forgerock.opendj.io.timeout", 0);
+        DEFAULT_CONNECT_TIMEOUT = getIntProperty("org.forgerock.opendj.io.connectTimeout", 5000);
+    }
+
     private SSLContext sslContext;
     private boolean useStartTLS;
-    private long timeoutInMillis;
-    private DecodeOptions decodeOptions;
-    private List<String> enabledCipherSuites = new LinkedList<String>();
-    private List<String> enabledProtocols = new LinkedList<String>();
-    private TCPNIOTransport transport;
+    private long timeoutInMillis = DEFAULT_TIMEOUT;
+    private long connectTimeoutInMillis = DEFAULT_CONNECT_TIMEOUT;
+    private final List<String> enabledCipherSuites = new LinkedList<String>();
+    private final List<String> enabledProtocols = new LinkedList<String>();
 
     /**
      * Creates a new set of connection options with default settings. SSL will
      * not be enabled, and a default set of decode options will be used.
      */
     public LDAPOptions() {
-        this.sslContext = null;
-        this.timeoutInMillis = 0;
-        this.useStartTLS = false;
-        this.decodeOptions = new DecodeOptions();
-        this.transport = null;
+        super();
     }
 
     /**
@@ -85,24 +88,93 @@
      *            The set of connection options to be copied.
      */
     public LDAPOptions(final LDAPOptions options) {
+        super(options);
         this.sslContext = options.sslContext;
         this.timeoutInMillis = options.timeoutInMillis;
         this.useStartTLS = options.useStartTLS;
-        this.decodeOptions = new DecodeOptions(options.decodeOptions);
         this.enabledCipherSuites.addAll(options.getEnabledCipherSuites());
         this.enabledProtocols.addAll(options.getEnabledProtocols());
-        this.transport = options.transport;
+        this.connectTimeoutInMillis = options.connectTimeoutInMillis;
     }
 
     /**
-     * Returns the decoding options which will be used to control how requests
-     * and responses are decoded.
+     * Adds the cipher suites enabled for secure connections with the Directory
+     * Server.
+     * <p>
+     * The suites must be supported by the SSLContext specified in
+     * {@link #setSSLContext(SSLContext)}. Following a successful call to this
+     * method, only the suites listed in the protocols parameter are enabled for
+     * use.
      *
-     * @return The decoding options which will be used to control how requests
-     *         and responses are decoded (never {@code null}).
+     * @param suites
+     *            Names of all the suites to enable.
+     * @return A reference to this set of options.
      */
-    public final DecodeOptions getDecodeOptions() {
-        return decodeOptions;
+    public LDAPOptions addEnabledCipherSuite(final String... suites) {
+        for (final String suite : suites) {
+            enabledCipherSuites.add(ensureNotNull(suite));
+        }
+        return this;
+    }
+
+    /**
+     * Adds the protocol versions enabled for secure connections with the
+     * Directory Server.
+     * <p>
+     * The protocols must be supported by the SSLContext specified in
+     * {@link #setSSLContext(SSLContext)}. Following a successful call to this
+     * method, only the protocols listed in the protocols parameter are enabled
+     * for use.
+     *
+     * @param protocols
+     *            Names of all the protocols to enable.
+     * @return A reference to this set of options.
+     */
+    public LDAPOptions addEnabledProtocol(final String... protocols) {
+        for (final String protocol : protocols) {
+            enabledProtocols.add(ensureNotNull(protocol));
+        }
+        return this;
+    }
+
+    /**
+     * Returns the connect timeout in the specified unit. If a connection is not
+     * established within the timeout period, then a
+     * {@link TimeoutResultException} error result will be returned. A timeout
+     * setting of 0 causes the OS connect timeout to be used.
+     * <p>
+     * The default operation timeout is 10 seconds and may be configured using
+     * the {@code org.forgerock.opendj.io.connectTimeout} property.
+     *
+     * @param unit
+     *            The time unit.
+     * @return The connect timeout, which may be 0 if there is no connect
+     *         timeout.
+     */
+    public long getConnectTimeout(final TimeUnit unit) {
+        return unit.convert(connectTimeoutInMillis, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Returns the names of the protocol versions which are currently enabled
+     * for secure connections with the Directory Server.
+     *
+     * @return An array of protocols or empty set if the default protocols are
+     *         to be used.
+     */
+    public List<String> getEnabledCipherSuites() {
+        return enabledCipherSuites;
+    }
+
+    /**
+     * Returns the names of the protocol versions which are currently enabled
+     * for secure connections with the Directory Server.
+     *
+     * @return An array of protocols or empty set if the default protocols are
+     *         to be used.
+     */
+    public List<String> getEnabledProtocols() {
+        return enabledProtocols;
     }
 
     /**
@@ -118,51 +190,47 @@
      *         connections with the Directory Server, which may be {@code null}
      *         indicating that connections will not be secured.
      */
-    public final SSLContext getSSLContext() {
+    public SSLContext getSSLContext() {
         return sslContext;
     }
 
     /**
-     * Returns the Grizzly TCP transport which will be used when initiating
-     * connections with the Directory Server.
+     * Returns the operation timeout in the specified unit. If a response is not
+     * received from the Directory Server within the timeout period, then the
+     * operation will be abandoned and a {@link TimeoutResultException} error
+     * result returned. A timeout setting of 0 disables operation timeout
+     * limits.
      * <p>
-     * By default this method will return {@code null} indicating that the
-     * default transport factory should be used to obtain a TCP transport.
-     *
-     * @return The Grizzly TCP transport which will be used when initiating
-     *         connections with the Directory Server, or {@code null} if the
-     *         default transport factory should be used to obtain a TCP
-     *         transport.
-     */
-    public final TCPNIOTransport getTCPNIOTransport() {
-        return transport;
-    }
-
-    /**
-     * Returns the operation timeout in the specified unit.
+     * The default operation timeout is 0 (no timeout) and may be configured
+     * using the {@code org.forgerock.opendj.io.timeout} property.
      *
      * @param unit
-     *            The time unit of use.
-     * @return The operation timeout.
+     *            The time unit.
+     * @return The operation timeout, which may be 0 if there is no operation
+     *         timeout.
      */
-    public final long getTimeout(final TimeUnit unit) {
+    public long getTimeout(final TimeUnit unit) {
         return unit.convert(timeoutInMillis, TimeUnit.MILLISECONDS);
     }
 
     /**
-     * Sets the decoding options which will be used to control how requests and
-     * responses are decoded.
+     * Sets the connect timeout. If a connection is not established within the
+     * timeout period, then a {@link TimeoutResultException} error result will
+     * be returned. A timeout setting of 0 causes the OS connect timeout to be
+     * used.
+     * <p>
+     * The default operation timeout is 10 seconds and may be configured using
+     * the {@code org.forgerock.opendj.io.connectTimeout} property.
      *
-     * @param decodeOptions
-     *            The decoding options which will be used to control how
-     *            requests and responses are decoded (never {@code null}).
-     * @return A reference to this LDAP connection options.
-     * @throws NullPointerException
-     *             If {@code decodeOptions} was {@code null}.
+     * @param timeout
+     *            The connect timeout, which may be 0 if there is no connect
+     *            timeout.
+     * @param unit
+     *            The time unit.
+     * @return A reference to this set of options.
      */
-    public final LDAPOptions setDecodeOptions(final DecodeOptions decodeOptions) {
-        Validator.ensureNotNull(decodeOptions);
-        this.decodeOptions = decodeOptions;
+    public LDAPOptions setConnectTimeout(final long timeout, final TimeUnit unit) {
+        this.connectTimeoutInMillis = unit.toMillis(timeout);
         return this;
     }
 
@@ -179,45 +247,30 @@
      *            The SSL context which will be used when initiating secure
      *            connections with the Directory Server, which may be
      *            {@code null} indicating that connections will not be secured.
-     * @return A reference to this LDAP connection options.
+     * @return A reference to this set of options.
      */
-    public final LDAPOptions setSSLContext(final SSLContext sslContext) {
+    public LDAPOptions setSSLContext(final SSLContext sslContext) {
         this.sslContext = sslContext;
         return this;
     }
 
     /**
-     * Sets the Grizzly TCP transport which will be used when initiating
-     * connections with the Directory Server.
+     * Sets the operation timeout. If a response is not received from the
+     * Directory Server within the timeout period, then the operation will be
+     * abandoned and a {@link TimeoutResultException} error result returned. A
+     * timeout setting of 0 disables operation timeout limits.
      * <p>
-     * By default this method will return {@code null} indicating that the
-     * default transport factory will be used to obtain a TCP transport.
-     *
-     * @param transport
-     *            The Grizzly TCP transport which will be used when initiating
-     *            connections with the Directory Server, or {@code null} if the
-     *            default transport factory should be used to obtain a TCP
-     *            transport.
-     * @return A reference to this LDAP connection options.
-     */
-    public final LDAPOptions setTCPNIOTransport(final TCPNIOTransport transport) {
-        this.transport = transport;
-        return this;
-    }
-
-    /**
-     * Sets the operation timeout. If the response is not received from the
-     * Directory Server in the timeout period, the operation will be abandoned
-     * and an error result returned. A timeout setting of 0 disables timeout
-     * limits.
+     * The default operation timeout is 0 (no timeout) and may be configured
+     * using the {@code org.forgerock.opendj.io.timeout} property.
      *
      * @param timeout
-     *            The operation timeout to use.
+     *            The operation timeout, which may be 0 if there is no operation
+     *            timeout.
      * @param unit
-     *            the time unit of the time argument.
-     * @return A reference to this LDAP connection options.
+     *            The time unit.
+     * @return A reference to this set of options.
      */
-    public final LDAPOptions setTimeout(final long timeout, final TimeUnit unit) {
+    public LDAPOptions setTimeout(final long timeout, final TimeUnit unit) {
         this.timeoutInMillis = unit.toMillis(timeout);
         return this;
     }
@@ -232,9 +285,9 @@
      *            {@code true} if StartTLS should be used for securing
      *            connections when an SSL context is specified, otherwise
      *            {@code false} indicating that SSL should be used.
-     * @return A reference to this LDAP connection options.
+     * @return A reference to this set of options.
      */
-    public final LDAPOptions setUseStartTLS(final boolean useStartTLS) {
+    public LDAPOptions setUseStartTLS(final boolean useStartTLS) {
         this.useStartTLS = useStartTLS;
         return this;
     }
@@ -249,70 +302,30 @@
      *         when an SSL context is specified, otherwise {@code false}
      *         indicating that SSL should be used.
      */
-    public final boolean useStartTLS() {
+    public boolean useStartTLS() {
         return useStartTLS;
     }
 
     /**
-     * Adds the protocol versions enabled for secure connections with the
-     * Directory Server.
-     * <p>
-     * The protocols must be supported by the SSLContext specified in
-     * {@link #setSSLContext(SSLContext)}. Following a successful call to this
-     * method, only the protocols listed in the protocols parameter are enabled
-     * for use.
-     *
-     * @param protocols
-     *            Names of all the protocols to enable.
-     * @return A reference to this LDAP connection options.
+     * {@inheritDoc}
      */
-    public final LDAPOptions addEnabledProtocol(String... protocols) {
-        for (final String protocol : protocols) {
-            enabledProtocols.add(Validator.ensureNotNull(protocol));
-        }
+    @Override
+    public LDAPOptions setDecodeOptions(DecodeOptions decodeOptions) {
+        // This method is required for binary compatibility.
+        return super.setDecodeOptions(decodeOptions);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public LDAPOptions setTCPNIOTransport(TCPNIOTransport transport) {
+        // This method is required for binary compatibility.
+        return super.setTCPNIOTransport(transport);
+    }
+
+    @Override
+    LDAPOptions getThis() {
         return this;
     }
-
-    /**
-     * Adds the cipher suites enabled for secure connections with the Directory
-     * Server.
-     * <p>
-     * The suites must be supported by the SSLContext specified in
-     * {@link #setSSLContext(SSLContext)}. Following a successful call to this
-     * method, only the suites listed in the protocols parameter are enabled for
-     * use.
-     *
-     * @param suites
-     *            Names of all the suites to enable.
-     * @return A reference to this LDAP connection options.
-     */
-    public final LDAPOptions addEnabledCipherSuite(String... suites) {
-        for (final String suite : suites) {
-            enabledCipherSuites.add(Validator.ensureNotNull(suite));
-        }
-        return this;
-    }
-
-    /**
-     * Returns the names of the protocol versions which are currently enabled
-     * for secure connections with the Directory Server.
-     *
-     * @return An array of protocols or empty set if the default protocols are
-     *         to be used.
-     */
-    public final List<String> getEnabledProtocols() {
-        return enabledProtocols;
-    }
-
-    /**
-     * Returns the names of the protocol versions which are currently enabled
-     * for secure connections with the Directory Server.
-     *
-     * @return An array of protocols or empty set if the default protocols are
-     *         to be used.
-     */
-    public final List<String> getEnabledCipherSuites() {
-        return enabledCipherSuites;
-    }
-
 }

--
Gitblit v1.10.0