From 122f2a984f9aaf7a2bc363c6971b94e3663f129b Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 28 Oct 2013 15:35:48 +0000
Subject: [PATCH] Fix OPENDJ-175: Decouple OpenDJ LDAP SDK from Grizzly CR-2513
---
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPBaseFilter.java | 131 ++++++++++++++++++++++++++++++++
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java | 38 ++-------
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java | 45 +++--------
3 files changed, 152 insertions(+), 62 deletions(-)
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPBaseFilter.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPBaseFilter.java
new file mode 100644
index 0000000..8236aa4
--- /dev/null
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPBaseFilter.java
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2013 ForgeRock AS.
+ */
+package com.forgerock.opendj.grizzly;
+
+import java.io.IOException;
+
+import org.forgerock.opendj.io.LDAPReader;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.spi.LDAPMessageHandler;
+import org.glassfish.grizzly.Buffer;
+import org.glassfish.grizzly.filterchain.BaseFilter;
+import org.glassfish.grizzly.filterchain.FilterChainContext;
+import org.glassfish.grizzly.filterchain.NextAction;
+
+/**
+ * Base class for LDAP-enabled filter.
+ * <p>
+ * Provides a common {@code handleRead()} method for both client and server
+ * filters.
+ */
+public abstract class LDAPBaseFilter extends BaseFilter {
+
+ /**
+ * The maximum BER element size, or <code>0</code> to indicate that there is
+ * no limit.
+ */
+ protected final int maxASN1ElementSize;
+
+ /**
+ * Allow to control how to decode requests and responses.
+ */
+ protected final DecodeOptions decodeOptions;
+
+ /**
+ * Creates a filter with provided decode options and max size of
+ * ASN1 element.
+ *
+ * @param options
+ * control how to decode requests and responses
+ * @param maxASN1ElementSize
+ * The maximum BER element size, or <code>0</code> to indicate
+ * that there is no limit.
+ */
+ protected LDAPBaseFilter(final DecodeOptions options, final int maxASN1ElementSize) {
+ this.decodeOptions = options;
+ this.maxASN1ElementSize = maxASN1ElementSize;
+ }
+
+ @Override
+ public final NextAction handleRead(final FilterChainContext ctx) throws IOException {
+ final LDAPBaseHandler handler = getLDAPHandler(ctx);
+ final LDAPReader<ASN1BufferReader> reader = handler.getReader();
+ final ASN1BufferReader asn1Reader = reader.getASN1Reader();
+ final Buffer buffer = (Buffer) ctx.getMessage();
+
+ asn1Reader.appendBytesRead(buffer);
+ try {
+ while (reader.hasMessageAvailable()) {
+ reader.readMessage(handler);
+ }
+ } catch (IOException e) {
+ handleReadException(ctx, e);
+ throw e;
+ } finally {
+ asn1Reader.disposeBytesRead();
+ }
+
+ return ctx.getStopAction();
+ }
+
+ /**
+ * Handle an exception occuring during a read within the
+ * {@code handleRead()} method.
+ *
+ * @param ctx
+ * context when reading
+ * @param e
+ * exception occuring while reading
+ */
+ protected abstract void handleReadException(FilterChainContext ctx, IOException e);
+
+ /**
+ * Interface for the {@code LDAPMessageHandler} used in the filter, that
+ * must be able to retrieve a Grizzly reader.
+ */
+ protected interface LDAPBaseHandler extends LDAPMessageHandler {
+ /**
+ * Returns the LDAP reader for this handler.
+ * @return the reader
+ */
+ LDAPReader<ASN1BufferReader> getReader();
+ }
+
+ /**
+ * Returns the LDAP message handler associated to the underlying connection
+ * of the provided context.
+ * <p>
+ * If no handler exists yet for the underlying connection, a new one is
+ * created and recorded for the connection.
+ *
+ * @param ctx
+ * current filter chain context
+ * @return the response handler associated to the connection, which can be a
+ * new one if no handler have been created yet
+ */
+ protected abstract LDAPBaseHandler getLDAPHandler(final FilterChainContext ctx);
+
+}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java
index a529127..0331276 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java
@@ -64,12 +64,10 @@
import org.forgerock.opendj.ldap.spi.LDAPFutureResultImpl;
import org.forgerock.opendj.ldap.spi.LDAPSearchFutureResultImpl;
import org.forgerock.opendj.ldap.spi.UnexpectedResponseException;
-import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.EmptyCompletionHandler;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.attributes.Attribute;
-import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction;
@@ -77,17 +75,14 @@
* Grizzly filter implementation for decoding LDAP responses and handling client
* side logic for SSL and SASL operations over LDAP.
*/
-final class LDAPClientFilter extends BaseFilter {
+final class LDAPClientFilter extends LDAPBaseFilter {
private static final Attribute<GrizzlyLDAPConnection> LDAP_CONNECTION_ATTR =
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPClientConnection");
private static final Attribute<ClientResponseHandler> RESPONSE_HANDLER_ATTR =
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("ClientResponseHandler");
- private final int maxASN1ElementSize;
- private final DecodeOptions decodeOptions;
-
- private static final class ClientResponseHandler extends AbstractLDAPMessageHandler {
+ static final class ClientResponseHandler extends AbstractLDAPMessageHandler implements LDAPBaseHandler {
private final LDAPReader<ASN1BufferReader> reader;
private FilterChainContext context;
@@ -486,8 +481,7 @@
* that there is no limit.
*/
LDAPClientFilter(final DecodeOptions options, final int maxASN1ElementSize) {
- this.decodeOptions = options;
- this.maxASN1ElementSize = maxASN1ElementSize;
+ super(options, maxASN1ElementSize);
}
@Override
@@ -524,30 +518,14 @@
return ctx.getInvokeAction();
}
+
@Override
- public NextAction handleRead(final FilterChainContext ctx) throws IOException {
- final ClientResponseHandler handler = getResponseHandler(ctx);
- final LDAPReader<ASN1BufferReader> reader = handler.getReader();
- final ASN1BufferReader asn1Reader = reader.getASN1Reader();
- final Buffer buffer = (Buffer) ctx.getMessage();
-
- asn1Reader.appendBytesRead(buffer);
- try {
- while (reader.hasMessageAvailable()) {
- reader.readMessage(handler);
- }
- } catch (IOException e) {
- final GrizzlyLDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- final Result errorResult =
- Responses.newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR).setCause(e)
- .setDiagnosticMessage(e.getMessage());
- ldapConnection.close(null, false, errorResult);
- throw e;
- } finally {
- asn1Reader.disposeBytesRead();
- }
-
- return ctx.getStopAction();
+ protected final void handleReadException(FilterChainContext ctx, IOException e) {
+ final GrizzlyLDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx.getConnection());
+ final Result errorResult =
+ Responses.newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR).setCause(e)
+ .setDiagnosticMessage(e.getMessage());
+ ldapConnection.close(null, false, errorResult);
}
/**
@@ -562,7 +540,8 @@
* @return the response handler associated to the context, which can be a
* new one if no handler have been created yet
*/
- private ClientResponseHandler getResponseHandler(final FilterChainContext ctx) {
+ @Override
+ protected final LDAPBaseHandler getLDAPHandler(final FilterChainContext ctx) {
Connection<?> connection = ctx.getConnection();
ClientResponseHandler handler = RESPONSE_HANDLER_ATTR.get(connection);
if (handler == null) {
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java
index 33c5d61..eea9d48 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java
@@ -75,11 +75,9 @@
import org.forgerock.opendj.ldap.spi.AbstractLDAPMessageHandler;
import org.forgerock.opendj.ldap.spi.UnexpectedRequestException;
import org.forgerock.opendj.ldap.spi.UnsupportedMessageException;
-import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.attributes.Attribute;
-import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.Filter;
import org.glassfish.grizzly.filterchain.FilterChain;
import org.glassfish.grizzly.filterchain.FilterChainContext;
@@ -94,7 +92,7 @@
* Grizzly filter implementation for decoding LDAP requests and handling server
* side logic for SSL and SASL operations over LDAP.
*/
-final class LDAPServerFilter extends BaseFilter {
+final class LDAPServerFilter extends LDAPBaseFilter {
/**
* Provides an arbitrary write operation on a LDAP writer.
@@ -659,10 +657,9 @@
}
private final GrizzlyLDAPListener listener;
- private final int maxASN1ElementSize;
- private final DecodeOptions decodeOptions;
- private static final class ServerRequestHandler extends AbstractLDAPMessageHandler {
+ private static final class ServerRequestHandler
+ extends AbstractLDAPMessageHandler implements LDAPBaseHandler {
private final Connection<?> connection;
private final LDAPReader<ASN1BufferReader> reader;
@@ -830,10 +827,8 @@
*/
LDAPServerFilter(final GrizzlyLDAPListener listener, final DecodeOptions options,
final int maxASN1ElementSize) {
+ super(options, maxASN1ElementSize <= 0 ? DEFAULT_MAX_REQUEST_SIZE : maxASN1ElementSize);
this.listener = listener;
- this.decodeOptions = options;
- this.maxASN1ElementSize =
- maxASN1ElementSize <= 0 ? DEFAULT_MAX_REQUEST_SIZE : maxASN1ElementSize;
}
@Override
@@ -875,25 +870,8 @@
}
@Override
- public NextAction handleRead(final FilterChainContext ctx) throws IOException {
- final ServerRequestHandler requestHandler = getRequestHandler(ctx.getConnection());
- final LDAPReader<ASN1BufferReader> reader = requestHandler.getReader();
- final ASN1BufferReader asn1Reader = reader.getASN1Reader();
- final Buffer buffer = (Buffer) ctx.getMessage();
-
- asn1Reader.appendBytesRead(buffer);
- try {
- while (reader.hasMessageAvailable()) {
- reader.readMessage(requestHandler);
- }
- } catch (IOException e) {
- exceptionOccurred(ctx, e);
- throw e;
- } finally {
- asn1Reader.disposeBytesRead();
- }
-
- return ctx.getStopAction();
+ protected final void handleReadException(FilterChainContext ctx, IOException e) {
+ exceptionOccurred(ctx, e);
}
/**
@@ -907,7 +885,9 @@
* @return the response handler associated to the context, which can be a
* new one if no handler have been created yet
*/
- private ServerRequestHandler getRequestHandler(final Connection<?> connection) {
+ @Override
+ protected final LDAPBaseHandler getLDAPHandler(final FilterChainContext ctx) {
+ Connection<?> connection = ctx.getConnection();
ServerRequestHandler handler = REQUEST_HANDLER_ATTR.get(connection);
if (handler == null) {
LDAPReader<ASN1BufferReader> reader = GrizzlyUtils.createReader(decodeOptions,
--
Gitblit v1.10.0