From eb78aabadc36e75ca680d12d80de7dcb3f6b6b20 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 24 Nov 2015 00:25:24 +0000
Subject: [PATCH] OPENDJ-1607 Merge HeartBeatConnectionFactory and AuthenticatedConnectionFactory into LDAPConnectionFactory
---
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java | 79 +++++++++++++++++++++++++++++++--------
1 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java b/opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
index a2c2ab4..0c31689 100644
--- a/opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
+++ b/opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
@@ -26,11 +26,21 @@
*/
package org.forgerock.opendj.grizzly;
+import static com.forgerock.opendj.grizzly.GrizzlyMessages.LDAP_CONNECTION_BIND_OR_START_TLS_CONNECTION_TIMEOUT;
+import static com.forgerock.opendj.grizzly.GrizzlyMessages.LDAP_CONNECTION_BIND_OR_START_TLS_REQUEST_TIMEOUT;
+import static com.forgerock.opendj.grizzly.GrizzlyMessages.LDAP_CONNECTION_REQUEST_TIMEOUT;
+import static org.forgerock.opendj.ldap.LDAPConnectionFactory.REQUEST_TIMEOUT;
+import static org.forgerock.opendj.ldap.LdapException.newLdapException;
+import static org.forgerock.opendj.ldap.ResultCode.CLIENT_SIDE_LOCAL_ERROR;
+import static org.forgerock.opendj.ldap.responses.Responses.newResult;
+import static org.forgerock.opendj.ldap.spi.LdapPromises.*;
+
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -40,7 +50,6 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.io.LDAPWriter;
-import org.forgerock.opendj.ldap.AbstractAsynchronousConnection;
import org.forgerock.opendj.ldap.ConnectionEventListener;
import org.forgerock.opendj.ldap.Connections;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
@@ -61,6 +70,7 @@
import org.forgerock.opendj.ldap.requests.GenericBindRequest;
import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
+import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.requests.StartTLSExtendedRequest;
import org.forgerock.opendj.ldap.requests.UnbindRequest;
@@ -71,24 +81,23 @@
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.spi.BindResultLdapPromiseImpl;
import org.forgerock.opendj.ldap.spi.ExtendedResultLdapPromiseImpl;
+import org.forgerock.opendj.ldap.spi.LDAPConnectionImpl;
import org.forgerock.opendj.ldap.spi.ResultLdapPromiseImpl;
import org.forgerock.opendj.ldap.spi.SearchResultLdapPromiseImpl;
import org.forgerock.util.Options;
import org.forgerock.util.Reject;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.PromiseImpl;
+import org.forgerock.util.time.Duration;
import org.glassfish.grizzly.CompletionHandler;
+import org.glassfish.grizzly.EmptyCompletionHandler;
import org.glassfish.grizzly.filterchain.Filter;
import org.glassfish.grizzly.filterchain.FilterChain;
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
import org.glassfish.grizzly.ssl.SSLFilter;
-import static org.forgerock.opendj.ldap.LDAPConnectionFactory.*;
-import static org.forgerock.opendj.ldap.LdapException.*;
-import static org.forgerock.opendj.ldap.spi.LdapPromises.*;
-
-import static com.forgerock.opendj.grizzly.GrizzlyMessages.*;
-
/** LDAP connection implementation. */
-final class GrizzlyLDAPConnection extends AbstractAsynchronousConnection implements TimeoutEventListener {
+final class GrizzlyLDAPConnection implements LDAPConnectionImpl, TimeoutEventListener {
/**
* A dummy SSL client engine configurator as SSLFilter only needs client
* config. This prevents Grizzly from needlessly using JVM defaults which
@@ -112,6 +121,7 @@
private final AtomicInteger nextMsgID = new AtomicInteger(1);
private final GrizzlyLDAPConnectionFactory factory;
private final ConcurrentHashMap<Integer, ResultLdapPromiseImpl<?, ?>> pendingRequests = new ConcurrentHashMap<>();
+ private final long requestTimeoutMS;
private final Object stateLock = new Object();
/** Guarded by stateLock. */
private Result connectionInvalidReason;
@@ -133,6 +143,8 @@
final GrizzlyLDAPConnectionFactory factory) {
this.connection = connection;
this.factory = factory;
+ final Duration requestTimeout = factory.getLDAPOptions().get(REQUEST_TIMEOUT);
+ this.requestTimeoutMS = requestTimeout.isUnlimited() ? 0 : requestTimeout.to(TimeUnit.MILLISECONDS);
}
@Override
@@ -306,6 +318,11 @@
}
@Override
+ public void close() {
+ close(Requests.newUnbindRequest(), null);
+ }
+
+ @Override
public void close(final UnbindRequest request, final String reason) {
// FIXME: I18N need to internationalize this message.
Reject.ifNull(request);
@@ -548,17 +565,16 @@
@Override
public long handleTimeout(final long currentTime) {
- final long timeout = factory.getLDAPOptions().get(TIMEOUT_IN_MILLISECONDS);
- if (timeout <= 0) {
+ if (requestTimeoutMS <= 0) {
return 0;
}
- long delay = timeout;
+ long delay = requestTimeoutMS;
for (final ResultLdapPromiseImpl<?, ?> promise : pendingRequests.values()) {
if (promise == null || !promise.checkForTimeout()) {
continue;
}
- final long diff = (promise.getTimestamp() + timeout) - currentTime;
+ final long diff = (promise.getTimestamp() + requestTimeoutMS) - currentTime;
if (diff > 0) {
// Will expire in diff milliseconds.
delay = Math.min(delay, diff);
@@ -577,17 +593,17 @@
logger.debug(LocalizableMessage.raw("Failing bind or StartTLS request due to timeout %s"
+ "(connection will be invalidated): ", promise));
final Result result = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT).setDiagnosticMessage(
- LDAP_CONNECTION_BIND_OR_START_TLS_REQUEST_TIMEOUT.get(timeout).toString());
+ LDAP_CONNECTION_BIND_OR_START_TLS_REQUEST_TIMEOUT.get(requestTimeoutMS).toString());
promise.adaptErrorResult(result);
// Fail the connection.
final Result errorResult = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT).setDiagnosticMessage(
- LDAP_CONNECTION_BIND_OR_START_TLS_CONNECTION_TIMEOUT.get(timeout).toString());
+ LDAP_CONNECTION_BIND_OR_START_TLS_CONNECTION_TIMEOUT.get(requestTimeoutMS).toString());
connectionErrorOccurred(errorResult);
} else {
logger.debug(LocalizableMessage.raw("Failing request due to timeout: %s", promise));
final Result result = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT).setDiagnosticMessage(
- LDAP_CONNECTION_REQUEST_TIMEOUT.get(timeout).toString());
+ LDAP_CONNECTION_REQUEST_TIMEOUT.get(requestTimeoutMS).toString());
promise.adaptErrorResult(result);
/*
@@ -607,7 +623,7 @@
@Override
public long getTimeout() {
- return factory.getLDAPOptions().get(TIMEOUT_IN_MILLISECONDS);
+ return requestTimeoutMS;
}
/**
@@ -769,8 +785,37 @@
bindOrStartTLSInProgress.set(state);
}
+ @Override
+ public Promise<Void, LdapException> enableTLS(
+ final SSLContext sslContext,
+ final List<String> sslEnabledProtocols,
+ final List<String> sslEnabledCipherSuites) {
+ final PromiseImpl<Void, LdapException> promise = PromiseImpl.create();
+ final EmptyCompletionHandler<SSLEngine> completionHandler = new EmptyCompletionHandler<SSLEngine>() {
+ @Override
+ public void completed(final SSLEngine result) {
+ promise.handleResult(null);
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
+ final Result errorResult = newResult(CLIENT_SIDE_LOCAL_ERROR)
+ .setCause(throwable).setDiagnosticMessage("SSL handshake failed");
+ connectionErrorOccurred(errorResult);
+ promise.handleException(newLdapException(errorResult));
+ }
+ };
+
+ try {
+ startTLS(sslContext, sslEnabledProtocols, sslEnabledCipherSuites, completionHandler);
+ } catch (final IOException e) {
+ completionHandler.failed(e);
+ }
+ return promise;
+ }
+
void startTLS(final SSLContext sslContext, final List<String> protocols, final List<String> cipherSuites,
- final CompletionHandler<SSLEngine> completionHandler) throws IOException {
+ final CompletionHandler<SSLEngine> completionHandler) throws IOException {
synchronized (stateLock) {
if (isTLSEnabled()) {
throw new IllegalStateException("TLS already enabled");
--
Gitblit v1.10.0