From 38fe921bd2d09734277828b638a4947e45a99bcd Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 25 Oct 2013 09:44:02 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-175: Decouple OpenDJ LDAP SDK from Grizzly
---
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedRequestException.java | 25
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferReader.java | 11
opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java | 2
opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/package-info.java | 31
opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPReader.java | 452 +++---
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/AbstractLDAPMessageHandler.java | 102
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPMessageHandler.java | 392 +++++
opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java | 4
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedResponseException.java | 23
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferWriter.java | 28
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPServerFilter.java | 621 ++++---
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPClientFilter.java | 775 +++++-----
opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPWriter.java | 724 ++++++++++
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnsupportedMessageException.java | 30
opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPReaderWriterTestCase.java | 61
/dev/null | 481 ------
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPListener.java | 2
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java | 7
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java | 123 +
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutChecker.java | 56
opendj3/opendj-core/src/test/java/org/forgerock/opendj/io/LDAPReaderWriterTestCase.java | 178 ++
opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutEventListener.java | 56
opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyUtils.java | 62
23 files changed, 2,755 insertions(+), 1,491 deletions(-)
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPReader.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPReader.java
similarity index 73%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPReader.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPReader.java
index 6e129f3..5323d2b 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPReader.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPReader.java
@@ -25,14 +25,11 @@
* Portions copyright 2011-2013 ForgeRock AS
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.io;
+import static com.forgerock.opendj.ldap.CoreMessages.*;
import static com.forgerock.opendj.ldap.LDAPConstants.*;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF;
-import static com.forgerock.opendj.ldap.CoreMessages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE;
-import static com.forgerock.opendj.util.StaticUtils.IO_LOG;
-import static com.forgerock.opendj.util.StaticUtils.byteToHex;
+import static com.forgerock.opendj.util.StaticUtils.*;
import java.io.IOException;
@@ -77,73 +74,99 @@
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.spi.LDAPMessageHandler;
import com.forgerock.opendj.ldap.LDAPUtils;
/**
- * Static methods for decoding LDAP messages.
+ * Responsible for reading LDAP messages.
+ *
+ * @param <R>
+ * type of ASN1 reader used to decode elements
*/
-final class LDAPReader {
+public final class LDAPReader<R extends ASN1Reader> {
+ private final R reader;
private final DecodeOptions options;
- LDAPReader(final DecodeOptions options) {
+ /**
+ * Creates a reader with the provided ASN1 reader and decoding options.
+ *
+ * @param asn1Reader
+ * reader capable of decoding ASN1 elements
+ * @param options
+ * allow to control how responses and requests are decoded
+ */
+ public LDAPReader(final R asn1Reader, final DecodeOptions options) {
+ this.reader = asn1Reader;
this.options = options;
}
/**
- * Decodes the elements from the provided ASN.1 reader as an LDAP message.
+ * Returns the ASN1 reader used to decode elements.
*
- * @param <P>
- * The type of {@code param}.
- * @param reader
- * The ASN.1 reader.
+ * @return ASN1 reader
+ */
+ public R getASN1Reader() {
+ return reader;
+ }
+
+ /**
+ * Read a LDAP message by decoding the elements from the provided ASN.1 asn1Reader.
+ *
* @param handler
* The <code>LDAPMessageHandler</code> that will handle a decoded
* message.
- * @param param
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- <P> void decode(final ASN1Reader reader, final LDAPMessageHandler<P> handler, final P param)
+ public void readMessage(final LDAPMessageHandler handler)
throws IOException {
reader.readStartSequence();
try {
final int messageID = (int) reader.readInteger();
- decodeProtocolOp(reader, messageID, handler, param);
+ readProtocolOp(messageID, handler);
} finally {
reader.readEndSequence();
}
}
/**
+ * Indicates whether or not the next message can be read without blocking.
+ *
+ * @return {@code true} if a complete element is available or {@code false}
+ * otherwise.
+ * @throws DecodeException
+ * If the available data was not valid ASN.1.
+ * @throws IOException
+ * If an unexpected IO error occurred.
+ */
+ public boolean hasMessageAvailable() throws DecodeException, IOException {
+ return reader.elementAvailable();
+ }
+
+ /**
* Decodes the elements from the provided ASN.1 read as an LDAP abandon
* request protocol op.
*
- * @param reader
- * The ASN.1 reader.
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeAbandonRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readAbandonRequest(final int messageID, final LDAPMessageHandler handler) throws IOException {
final int msgToAbandon = (int) reader.readInteger(OP_TYPE_ABANDON_REQUEST);
final AbandonRequest message = Requests.newAbandonRequest(msgToAbandon);
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP ABANDON REQUEST(messageID={}, request={})", messageID, message);
- handler.abandonRequest(p, messageID, message);
+ handler.abandonRequest(messageID, message);
}
/**
@@ -151,26 +174,24 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeAddRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readAddRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Entry entry;
reader.readStartSequence(OP_TYPE_ADD_REQUEST);
try {
final String dnString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
entry = options.getEntryFactory().newEntry(dn);
reader.readStartSequence();
@@ -179,7 +200,7 @@
reader.readStartSequence();
try {
final String ads = reader.readOctetStringAsString();
- final AttributeDescription ad = decodeAttributeDescription(ads, schema);
+ final AttributeDescription ad = readAttributeDescription(ads, schema);
final Attribute attribute = options.getAttributeFactory().newAttribute(ad);
reader.readStartSet();
@@ -203,11 +224,11 @@
}
final AddRequest message = Requests.newAddRequest(entry);
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP ADD REQUEST(messageID={}, request={})", messageID, message);
- handler.addRequest(p, messageID, message);
+ handler.addRequest(messageID, message);
}
/**
@@ -215,19 +236,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeAddResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readAddResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Result message;
reader.readStartSequence(OP_TYPE_ADD_RESPONSE);
@@ -238,19 +257,19 @@
message =
Responses.newResult(resultCode).setMatchedDN(matchedDN).setDiagnosticMessage(
diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP ADD RESULT(messageID={}, result={})", messageID, message);
- handler.addResult(p, messageID, message);
+ handler.addResult(messageID, message);
}
- private AttributeDescription decodeAttributeDescription(final String attributeDescription,
+ private AttributeDescription readAttributeDescription(final String attributeDescription,
final Schema schema) throws DecodeException {
try {
return AttributeDescription.valueOf(attributeDescription, schema);
@@ -264,19 +283,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeBindRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readBindRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
reader.readStartSequence(OP_TYPE_BIND_REQUEST);
try {
final int protocolVersion = (int) reader.readInteger();
@@ -287,12 +304,12 @@
final GenericBindRequest request =
Requests.newGenericBindRequest(authName, authType, authBytes);
- decodeControls(reader, request);
+ readControls(request);
IO_LOG.trace("DECODE LDAP BIND REQUEST(messageID={}, auth=0x{}, request={})", messageID,
byteToHex(request.getAuthenticationType()), request);
- handler.bindRequest(p, messageID, protocolVersion, request);
+ handler.bindRequest(messageID, protocolVersion, request);
} finally {
reader.readEndSequence();
}
@@ -303,19 +320,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeBindResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readBindResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
BindResult message;
reader.readStartSequence(OP_TYPE_BIND_RESPONSE);
@@ -326,7 +341,7 @@
message =
Responses.newBindResult(resultCode).setMatchedDN(matchedDN)
.setDiagnosticMessage(diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
if (reader.hasNextElement() && (reader.peekType() == TYPE_SERVER_SASL_CREDENTIALS)) {
message.setServerSASLCredentials(reader
.readOctetString(TYPE_SERVER_SASL_CREDENTIALS));
@@ -335,11 +350,11 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP BIND RESULT(messageID={}, result={})", messageID, message);
- handler.bindResult(p, messageID, message);
+ handler.bindResult(messageID, message);
}
/**
@@ -347,31 +362,29 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeCompareRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readCompareRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
CompareRequest message;
reader.readStartSequence(OP_TYPE_COMPARE_REQUEST);
try {
final String dnString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
reader.readStartSequence();
try {
final String ads = reader.readOctetStringAsString();
- final AttributeDescription ad = decodeAttributeDescription(ads, schema);
+ final AttributeDescription ad = readAttributeDescription(ads, schema);
final ByteString assertionValue = reader.readOctetString();
message = Requests.newCompareRequest(dn, ad, assertionValue);
} finally {
@@ -381,11 +394,11 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP COMPARE REQUEST(messageID={}, request={})", messageID, message);
- handler.compareRequest(p, messageID, message);
+ handler.compareRequest(messageID, message);
}
/**
@@ -393,19 +406,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeCompareResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readCompareResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
CompareResult message;
reader.readStartSequence(OP_TYPE_COMPARE_RESPONSE);
@@ -416,29 +427,29 @@
message =
Responses.newCompareResult(resultCode).setMatchedDN(matchedDN)
.setDiagnosticMessage(diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP COMPARE RESULT(messageID={}, result={})", messageID, message);
- handler.compareResult(p, messageID, message);
+ handler.compareResult(messageID, message);
}
/**
* Decodes the elements from the provided ASN.1 reader as an LDAP control.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param request
* The decoded request to decode controls for.
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private void decodeControl(final ASN1Reader reader, final Request request) throws IOException {
+ private void readControl(final Request request) throws IOException {
String oid;
boolean isCritical;
ByteString value;
@@ -466,13 +477,13 @@
* Decodes the elements from the provided ASN.1 reader as an LDAP control.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param response
* The decoded message to decode controls for.
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private void decodeControl(final ASN1Reader reader, final Response response) throws IOException {
+ private void readControl(final Response response) throws IOException {
String oid;
boolean isCritical;
ByteString value;
@@ -500,18 +511,18 @@
* Decodes the elements from the provided ASN.1 reader as a set of controls.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param request
* The decoded message to decode controls for.
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private void decodeControls(final ASN1Reader reader, final Request request) throws IOException {
+ private void readControls(final Request request) throws IOException {
if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE)) {
reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
try {
while (reader.hasNextElement()) {
- decodeControl(reader, request);
+ readControl(request);
}
} finally {
reader.readEndSequence();
@@ -523,19 +534,19 @@
* Decodes the elements from the provided ASN.1 reader as a set of controls.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param response
* The decoded message to decode controls for.
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private void decodeControls(final ASN1Reader reader, final Response response)
+ private void readControls(final Response response)
throws IOException {
if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE)) {
reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
try {
while (reader.hasNextElement()) {
- decodeControl(reader, response);
+ readControl(response);
}
} finally {
reader.readEndSequence();
@@ -548,29 +559,27 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeDeleteRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readDeleteRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
final String dnString = reader.readOctetStringAsString(OP_TYPE_DELETE_REQUEST);
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
final DeleteRequest message = Requests.newDeleteRequest(dn);
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP DELETE REQUEST(messageID={}, request={})", messageID, message);
- handler.deleteRequest(p, messageID, message);
+ handler.deleteRequest(messageID, message);
}
/**
@@ -578,19 +587,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeDeleteResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readDeleteResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Result message;
reader.readStartSequence(OP_TYPE_DELETE_RESPONSE);
@@ -601,19 +608,19 @@
message =
Responses.newResult(resultCode).setMatchedDN(matchedDN).setDiagnosticMessage(
diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP DELETE RESULT(messageID={}, result={})", messageID, message);
- handler.deleteResult(p, messageID, message);
+ handler.deleteResult(messageID, message);
}
- private DN decodeDN(final String dn, final Schema schema) throws DecodeException {
+ private DN readDN(final String dn, final Schema schema) throws DecodeException {
try {
return DN.valueOf(dn, schema);
} catch (final LocalizedIllegalArgumentException e) {
@@ -626,19 +633,17 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeExtendedRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readExtendedRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
String oid;
ByteString value;
@@ -655,11 +660,11 @@
final GenericExtendedRequest message = Requests.newGenericExtendedRequest(oid, value);
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP EXTENDED REQUEST(messageID={}, request={})", messageID, message);
- handler.extendedRequest(p, messageID, message);
+ handler.extendedRequest(messageID, message);
}
/**
@@ -667,19 +672,17 @@
* response protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeExtendedResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readExtendedResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
GenericExtendedResult message;
@@ -691,7 +694,7 @@
message =
Responses.newGenericExtendedResult(resultCode).setMatchedDN(matchedDN)
.setDiagnosticMessage(diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
if (reader.hasNextElement() && (reader.peekType() == TYPE_EXTENDED_RESPONSE_OID)) {
message.setOID(reader.readOctetStringAsString(TYPE_EXTENDED_RESPONSE_OID));
}
@@ -702,11 +705,11 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP EXTENDED RESULT(messageID={}, result={})", messageID, message);
- handler.extendedResult(p, messageID, message);
+ handler.extendedResult(messageID, message);
}
/**
@@ -714,19 +717,17 @@
* intermediate response protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeIntermediateResponse(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readIntermediateResponse(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
GenericIntermediateResponse message;
reader.readStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
@@ -742,12 +743,12 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP INTERMEDIATE RESPONSE(messageID={}, response={})",
messageID, message);
- handler.intermediateResponse(p, messageID, message);
+ handler.intermediateResponse(messageID, message);
}
/**
@@ -755,29 +756,27 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeModifyDNRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readModifyDNRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
ModifyDNRequest message;
reader.readStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
try {
final String dnString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
final String newRDNString = reader.readOctetStringAsString();
- final RDN newRDN = decodeRDN(newRDNString, schema);
+ final RDN newRDN = readRDN(newRDNString, schema);
message = Requests.newModifyDNRequest(dn, newRDN);
@@ -786,18 +785,18 @@
if (reader.hasNextElement() && (reader.peekType() == TYPE_MODIFY_DN_NEW_SUPERIOR)) {
final String newSuperiorString =
reader.readOctetStringAsString(TYPE_MODIFY_DN_NEW_SUPERIOR);
- final DN newSuperior = decodeDN(newSuperiorString, schema);
+ final DN newSuperior = readDN(newSuperiorString, schema);
message.setNewSuperior(newSuperior);
}
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP MODIFY DN REQUEST(messageID={}, request={})", messageID, message);
- handler.modifyDNRequest(p, messageID, message);
+ handler.modifyDNRequest(messageID, message);
}
/**
@@ -805,19 +804,17 @@
* response protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeModifyDNResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readModifyDNResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Result message;
reader.readStartSequence(OP_TYPE_MODIFY_DN_RESPONSE);
@@ -828,16 +825,16 @@
message =
Responses.newResult(resultCode).setMatchedDN(matchedDN).setDiagnosticMessage(
diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE MODIFY DN RESULT(messageID={}, result={})", messageID, message);
- handler.modifyDNResult(p, messageID, message);
+ handler.modifyDNResult(messageID, message);
}
/**
@@ -845,26 +842,24 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeModifyRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readModifyRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
ModifyRequest message;
reader.readStartSequence(OP_TYPE_MODIFY_REQUEST);
try {
final String dnString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
message = Requests.newModifyRequest(dn);
reader.readStartSequence();
@@ -882,7 +877,7 @@
reader.readStartSequence();
try {
final String ads = reader.readOctetStringAsString();
- final AttributeDescription ad = decodeAttributeDescription(ads, schema);
+ final AttributeDescription ad = readAttributeDescription(ads, schema);
final Attribute attribute =
options.getAttributeFactory().newAttribute(ad);
@@ -909,11 +904,11 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP MODIFY REQUEST(messageID={}, request={})", messageID, message);
- handler.modifyRequest(p, messageID, message);
+ handler.modifyRequest(messageID, message);
}
/**
@@ -921,19 +916,17 @@
* protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeModifyResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readModifyResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Result message;
reader.readStartSequence(OP_TYPE_MODIFY_RESPONSE);
@@ -944,16 +937,16 @@
message =
Responses.newResult(resultCode).setMatchedDN(matchedDN).setDiagnosticMessage(
diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP MODIFY RESULT(messageID={}, result={})", messageID, message);
- handler.modifyResult(p, messageID, message);
+ handler.modifyResult(messageID, message);
}
/**
@@ -961,24 +954,22 @@
* op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeProtocolOp(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readProtocolOp(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
final byte type = reader.peekType();
switch (type) {
case OP_TYPE_UNBIND_REQUEST: // 0x42
- decodeUnbindRequest(reader, messageID, handler, p);
+ readUnbindRequest(messageID, handler);
break;
case 0x43: // 0x43
case 0x44: // 0x44
@@ -987,20 +978,20 @@
case 0x47: // 0x47
case 0x48: // 0x48
case 0x49: // 0x49
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_DELETE_REQUEST: // 0x4A
- decodeDeleteRequest(reader, messageID, handler, p);
+ readDeleteRequest(messageID, handler);
break;
case 0x4B: // 0x4B
case 0x4C: // 0x4C
case 0x4D: // 0x4D
case 0x4E: // 0x4E
case 0x4F: // 0x4F
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_ABANDON_REQUEST: // 0x50
- decodeAbandonRequest(reader, messageID, handler, p);
+ readAbandonRequest(messageID, handler);
break;
case 0x51: // 0x51
case 0x52: // 0x52
@@ -1017,85 +1008,85 @@
case 0x5D: // 0x5D
case 0x5E: // 0x5E
case 0x5F: // 0x5F
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_BIND_REQUEST: // 0x60
- decodeBindRequest(reader, messageID, handler, p);
+ readBindRequest(messageID, handler);
break;
case OP_TYPE_BIND_RESPONSE: // 0x61
- decodeBindResult(reader, messageID, handler, p);
+ readBindResult(messageID, handler);
break;
case 0x62: // 0x62
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_SEARCH_REQUEST: // 0x63
- decodeSearchRequest(reader, messageID, handler, p);
+ readSearchRequest(messageID, handler);
break;
case OP_TYPE_SEARCH_RESULT_ENTRY: // 0x64
- decodeSearchResultEntry(reader, messageID, handler, p);
+ readSearchResultEntry(messageID, handler);
break;
case OP_TYPE_SEARCH_RESULT_DONE: // 0x65
- decodeSearchResult(reader, messageID, handler, p);
+ readSearchResult(messageID, handler);
break;
case OP_TYPE_MODIFY_REQUEST: // 0x66
- decodeModifyRequest(reader, messageID, handler, p);
+ readModifyRequest(messageID, handler);
break;
case OP_TYPE_MODIFY_RESPONSE: // 0x67
- decodeModifyResult(reader, messageID, handler, p);
+ readModifyResult(messageID, handler);
break;
case OP_TYPE_ADD_REQUEST: // 0x68
- decodeAddRequest(reader, messageID, handler, p);
+ readAddRequest(messageID, handler);
break;
case OP_TYPE_ADD_RESPONSE: // 0x69
- decodeAddResult(reader, messageID, handler, p);
+ readAddResult(messageID, handler);
break;
case 0x6A: // 0x6A
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_DELETE_RESPONSE: // 0x6B
- decodeDeleteResult(reader, messageID, handler, p);
+ readDeleteResult(messageID, handler);
break;
case OP_TYPE_MODIFY_DN_REQUEST: // 0x6C
- decodeModifyDNRequest(reader, messageID, handler, p);
+ readModifyDNRequest(messageID, handler);
break;
case OP_TYPE_MODIFY_DN_RESPONSE: // 0x6D
- decodeModifyDNResult(reader, messageID, handler, p);
+ readModifyDNResult(messageID, handler);
break;
case OP_TYPE_COMPARE_REQUEST: // 0x6E
- decodeCompareRequest(reader, messageID, handler, p);
+ readCompareRequest(messageID, handler);
break;
case OP_TYPE_COMPARE_RESPONSE: // 0x6F
- decodeCompareResult(reader, messageID, handler, p);
+ readCompareResult(messageID, handler);
break;
case 0x70: // 0x70
case 0x71: // 0x71
case 0x72: // 0x72
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_SEARCH_RESULT_REFERENCE: // 0x73
- decodeSearchResultReference(reader, messageID, handler, p);
+ readSearchResultReference(messageID, handler);
break;
case 0x74: // 0x74
case 0x75: // 0x75
case 0x76: // 0x76
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
case OP_TYPE_EXTENDED_REQUEST: // 0x77
- decodeExtendedRequest(reader, messageID, handler, p);
+ readExtendedRequest(messageID, handler);
break;
case OP_TYPE_EXTENDED_RESPONSE: // 0x78
- decodeExtendedResult(reader, messageID, handler, p);
+ readExtendedResult(messageID, handler);
break;
case OP_TYPE_INTERMEDIATE_RESPONSE: // 0x79
- decodeIntermediateResponse(reader, messageID, handler, p);
+ readIntermediateResponse(messageID, handler);
break;
default:
- handler.unrecognizedMessage(p, messageID, type, reader.readOctetString(type));
+ handler.unrecognizedMessage(messageID, type, reader.readOctetString(type));
break;
}
}
- private RDN decodeRDN(final String rdn, final Schema schema) throws DecodeException {
+ private RDN readRDN(final String rdn, final Schema schema) throws DecodeException {
try {
return RDN.valueOf(rdn, schema);
} catch (final LocalizedIllegalArgumentException e) {
@@ -1103,7 +1094,7 @@
}
}
- private void decodeResponseReferrals(final ASN1Reader reader, final Result message)
+ private void readResponseReferrals(final Result message)
throws IOException {
if (reader.hasNextElement() && (reader.peekType() == TYPE_REFERRAL_SEQUENCE)) {
reader.readStartSequence(TYPE_REFERRAL_SEQUENCE);
@@ -1123,26 +1114,24 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeSearchRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readSearchRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
SearchRequest message;
reader.readStartSequence(OP_TYPE_SEARCH_REQUEST);
try {
final String baseDNString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(baseDNString);
- final DN baseDN = decodeDN(baseDNString, schema);
+ final DN baseDN = readDN(baseDNString, schema);
final int scopeIntValue = reader.readEnumerated();
final SearchScope scope = SearchScope.valueOf(scopeIntValue);
@@ -1186,11 +1175,11 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP SEARCH REQUEST(messageID={}, request={})", messageID, message);
- handler.searchRequest(p, messageID, message);
+ handler.searchRequest(messageID, message);
}
/**
@@ -1198,19 +1187,17 @@
* done protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeSearchResult(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readSearchResult(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Result message;
@@ -1222,16 +1209,16 @@
message =
Responses.newResult(resultCode).setMatchedDN(matchedDN).setDiagnosticMessage(
diagnosticMessage);
- decodeResponseReferrals(reader, message);
+ readResponseReferrals(message);
} finally {
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP SEARCH RESULT(messageID={}, result={})", messageID, message);
- handler.searchResult(p, messageID, message);
+ handler.searchResult(messageID, message);
}
/**
@@ -1239,26 +1226,25 @@
* result entry protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
+
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeSearchResultEntry(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readSearchResultEntry(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
Entry entry;
reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
try {
final String dnString = reader.readOctetStringAsString();
final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
- final DN dn = decodeDN(dnString, schema);
+ final DN dn = readDN(dnString, schema);
entry = options.getEntryFactory().newEntry(dn);
reader.readStartSequence();
@@ -1267,7 +1253,7 @@
reader.readStartSequence();
try {
final String ads = reader.readOctetStringAsString();
- final AttributeDescription ad = decodeAttributeDescription(ads, schema);
+ final AttributeDescription ad = readAttributeDescription(ads, schema);
final Attribute attribute = options.getAttributeFactory().newAttribute(ad);
reader.readStartSet();
@@ -1291,11 +1277,11 @@
}
final SearchResultEntry message = Responses.newSearchResultEntry(entry);
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP SEARCH RESULT ENTRY(messageID={}, entry={})", messageID, message);
- handler.searchResultEntry(p, messageID, message);
+ handler.searchResultEntry(messageID, message);
}
/**
@@ -1303,19 +1289,17 @@
* reference protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeSearchResultReference(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readSearchResultReference(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
SearchResultReference message;
reader.readStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
@@ -1328,12 +1312,12 @@
reader.readEndSequence();
}
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP SEARCH RESULT REFERENCE(messageID={}, result={})",
messageID, message);
- handler.searchResultReference(p, messageID, message);
+ handler.searchResultReference(messageID, message);
}
/**
@@ -1341,27 +1325,25 @@
* request protocol op.
*
* @param reader
- * The ASN.1 reader.
+ * The ASN.1 reader
* @param messageID
* The decoded message ID for this message.
* @param handler
* The <code>LDAPMessageHandler</code> that will handle this
* decoded message.
- * @param p
- * The parameter to pass into the <code>LDAPMessageHandler</code>
* @throws IOException
* If an error occurred while reading bytes to decode.
*/
- private <P> void decodeUnbindRequest(final ASN1Reader reader, final int messageID,
- final LDAPMessageHandler<P> handler, final P p) throws IOException {
+ private void readUnbindRequest(final int messageID,
+ final LDAPMessageHandler handler) throws IOException {
UnbindRequest message;
reader.readNull(OP_TYPE_UNBIND_REQUEST);
message = Requests.newUnbindRequest();
- decodeControls(reader, message);
+ readControls(message);
IO_LOG.trace("DECODE LDAP UNBIND REQUEST(messageID={}, request={})", messageID, message);
- handler.unbindRequest(p, messageID, message);
+ handler.unbindRequest(messageID, message);
}
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPWriter.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPWriter.java
new file mode 100644
index 0000000..802524f
--- /dev/null
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPWriter.java
@@ -0,0 +1,724 @@
+/*
+ * 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 2009-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011-2013 ForgeRock AS
+ */
+
+package org.forgerock.opendj.io;
+
+import static com.forgerock.opendj.ldap.LDAPConstants.*;
+import static com.forgerock.opendj.util.StaticUtils.IO_LOG;
+import static com.forgerock.opendj.util.StaticUtils.byteToHex;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.forgerock.opendj.asn1.ASN1Writer;
+import org.forgerock.opendj.ldap.Attribute;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Modification;
+import org.forgerock.opendj.ldap.controls.Control;
+import org.forgerock.opendj.ldap.requests.AbandonRequest;
+import org.forgerock.opendj.ldap.requests.AddRequest;
+import org.forgerock.opendj.ldap.requests.CompareRequest;
+import org.forgerock.opendj.ldap.requests.DeleteRequest;
+import org.forgerock.opendj.ldap.requests.ExtendedRequest;
+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.Request;
+import org.forgerock.opendj.ldap.requests.SearchRequest;
+import org.forgerock.opendj.ldap.requests.UnbindRequest;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.CompareResult;
+import org.forgerock.opendj.ldap.responses.ExtendedResult;
+import org.forgerock.opendj.ldap.responses.IntermediateResponse;
+import org.forgerock.opendj.ldap.responses.Response;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.opendj.ldap.responses.SearchResultReference;
+
+import com.forgerock.opendj.ldap.LDAPUtils;
+import com.forgerock.opendj.util.StaticUtils;
+
+/**
+ * Responsible for writing LDAP messages.
+ *
+ * @param <W>
+ * type of ASN1 writer used to encode elements
+ */
+public final class LDAPWriter<W extends ASN1Writer> {
+
+ private final W writer;
+
+ /**
+ * Creates a writer based on the provided ASN1 writer.
+ *
+ * @param asn1Writer
+ * writer to encode ASN.1 elements
+ */
+ public LDAPWriter(W asn1Writer) {
+ this.writer = asn1Writer;
+ }
+
+ /**
+ * Returns the ASN1 writer used to encode elements.
+ *
+ * @return the ASN1 writer
+ */
+ public W getASN1Writer() {
+ return writer;
+ }
+
+ /**
+ * Write the provided control.
+ *
+ * @param control
+ * the control
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeControl(final Control control)
+ throws IOException {
+ writer.writeStartSequence();
+ writer.writeOctetString(control.getOID());
+ if (control.isCritical()) {
+ writer.writeBoolean(control.isCritical());
+ }
+ if (control.getValue() != null) {
+ writer.writeOctetString(control.getValue());
+ }
+ writer.writeEndSequence();
+ }
+
+ /**
+ * Write the provided entry.
+ *
+ * @param searchResultEntry
+ * entry
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeEntry(final SearchResultEntry searchResultEntry) throws IOException {
+ writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
+ writer.writeOctetString(searchResultEntry.getName().toString());
+
+ writer.writeStartSequence();
+ for (final Attribute attr : searchResultEntry.getAllAttributes()) {
+ writeAttribute(attr);
+ }
+ writer.writeEndSequence();
+ writer.writeEndSequence();
+ }
+
+ private void writeAttribute(final Attribute attribute)
+ throws IOException {
+ writer.writeStartSequence();
+ writer.writeOctetString(attribute.getAttributeDescriptionAsString());
+
+ writer.writeStartSet();
+ for (final ByteString value : attribute) {
+ writer.writeOctetString(value);
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ }
+
+ private void writeChange(final Modification change)
+ throws IOException {
+ writer.writeStartSequence();
+ writer.writeEnumerated(change.getModificationType().intValue());
+ writeAttribute(change.getAttribute());
+ writer.writeEndSequence();
+ }
+
+ private void writeMessageFooter(final Request request)
+ throws IOException {
+ final List<Control> controls = request.getControls();
+ if (!controls.isEmpty()) {
+ writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
+ for (final Control control : controls) {
+ writeControl(control);
+ }
+ writer.writeEndSequence();
+ }
+
+ writer.writeEndSequence();
+ }
+
+ private void writeMessageFooter(final Response response)
+ throws IOException {
+ final List<Control> controls = response.getControls();
+ if (!controls.isEmpty()) {
+ writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
+ for (final Control control : controls) {
+ writeControl(control);
+ }
+ writer.writeEndSequence();
+ }
+
+ writer.writeEndSequence();
+ }
+
+ private void writeMessageHeader(final int messageID)
+ throws IOException {
+ writer.writeStartSequence();
+ writer.writeInteger(messageID);
+ }
+
+ private void writeResultFooter(final ASN1Writer writer) throws IOException {
+ writer.writeEndSequence();
+ }
+
+ private void writeResultHeader(final byte typeTag,
+ final Result rawMessage) throws IOException {
+ writer.writeStartSequence(typeTag);
+ writer.writeEnumerated(rawMessage.getResultCode().intValue());
+ writer.writeOctetString(rawMessage.getMatchedDN());
+ writer.writeOctetString(rawMessage.getDiagnosticMessage());
+
+ final List<String> referralURIs = rawMessage.getReferralURIs();
+ if (!referralURIs.isEmpty()) {
+ writer.writeStartSequence(TYPE_REFERRAL_SEQUENCE);
+ for (final String s : referralURIs) {
+ writer.writeOctetString(s);
+ }
+ writer.writeEndSequence();
+ }
+ }
+
+ /**
+ * Write the provided abandon request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeAbandonRequest(final int messageID, final AbandonRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP ABANDON REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeInteger(OP_TYPE_ABANDON_REQUEST, request.getRequestID());
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided add request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeAddRequest(final int messageID, final AddRequest request)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP ADD REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_ADD_REQUEST);
+ writer.writeOctetString(request.getName().toString());
+
+ // Write the attributes
+ writer.writeStartSequence();
+ for (final Attribute attr : request.getAllAttributes()) {
+ writeAttribute(attr);
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided add result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeAddResult(final int messageID, final Result result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP ADD RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_ADD_RESPONSE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided bind request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param version
+ * version of the protocol
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeBindRequest(final int messageID, final int version,
+ final GenericBindRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP BIND REQUEST(messageID={}, auth=0x{}, request={})",
+ messageID, byteToHex(request.getAuthenticationType()), request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
+
+ writer.writeInteger(version);
+ writer.writeOctetString(request.getName());
+ writer.writeOctetString(request.getAuthenticationType(), request.getAuthenticationValue());
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided bind result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeBindResult(final int messageID, final BindResult result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP BIND RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_BIND_RESPONSE, result);
+
+ final ByteString saslCredentials = result.getServerSASLCredentials();
+ if (saslCredentials != null && saslCredentials.length() > 0) {
+ writer.writeOctetString(TYPE_SERVER_SASL_CREDENTIALS, result.getServerSASLCredentials());
+ }
+
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided compare request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeCompareRequest(final int messageID,
+ final CompareRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP COMPARE REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_COMPARE_REQUEST);
+ writer.writeOctetString(request.getName().toString());
+
+ writer.writeStartSequence();
+ writer.writeOctetString(request.getAttributeDescription().toString());
+ writer.writeOctetString(request.getAssertionValue());
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided compare result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeCompareResult(final int messageID,
+ final CompareResult result) throws IOException {
+ IO_LOG.trace("ENCODE LDAP COMPARE RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_COMPARE_RESPONSE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided delete request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeDeleteRequest(final int messageID,
+ final DeleteRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP DELETE REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeOctetString(OP_TYPE_DELETE_REQUEST, request.getName().toString());
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided delete result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeDeleteResult(final int messageID, final Result result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP DELETE RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_DELETE_RESPONSE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided extended request.
+ *
+ * @param <R>
+ * type of extended result returned by the request
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public <R extends ExtendedResult> void writeExtendedRequest(final int messageID,
+ final ExtendedRequest<R> request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP EXTENDED REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_EXTENDED_REQUEST);
+ writer.writeOctetString(TYPE_EXTENDED_REQUEST_OID, request.getOID());
+
+ final ByteString requestValue = request.getValue();
+ if (requestValue != null) {
+ writer.writeOctetString(TYPE_EXTENDED_REQUEST_VALUE, requestValue);
+ }
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided extended result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeExtendedResult(final int messageID,
+ final ExtendedResult result) throws IOException {
+ IO_LOG.trace("ENCODE LDAP EXTENDED RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_EXTENDED_RESPONSE, result);
+
+ final String responseName = result.getOID();
+ final ByteString responseValue = result.getValue();
+
+ if (responseName != null) {
+ writer.writeOctetString(TYPE_EXTENDED_RESPONSE_OID, responseName);
+ }
+
+ if (responseValue != null) {
+ writer.writeOctetString(TYPE_EXTENDED_RESPONSE_VALUE, responseValue);
+ }
+
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided intermediate response.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param response
+ * the response
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeIntermediateResponse(final int messageID,
+ final IntermediateResponse response) throws IOException {
+ IO_LOG.trace("ENCODE LDAP INTERMEDIATE RESPONSE(messageID={}, response={})", messageID, response);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
+
+ final String responseName = response.getOID();
+ final ByteString responseValue = response.getValue();
+
+ if (responseName != null) {
+ writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_OID, response.getOID());
+ }
+
+ if (responseValue != null) {
+ writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE, response.getValue());
+ }
+
+ writer.writeEndSequence();
+ writeMessageFooter(response);
+ }
+
+ /**
+ * Write the provided modify DN request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeModifyDNRequest(final int messageID,
+ final ModifyDNRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP MODIFY DN REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
+ writer.writeOctetString(request.getName().toString());
+ writer.writeOctetString(request.getNewRDN().toString());
+ writer.writeBoolean(request.isDeleteOldRDN());
+
+ final DN newSuperior = request.getNewSuperior();
+ if (newSuperior != null) {
+ writer.writeOctetString(TYPE_MODIFY_DN_NEW_SUPERIOR, newSuperior.toString());
+ }
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided modify DN result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeModifyDNResult(final int messageID, final Result result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP MODIFY DN RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_MODIFY_DN_RESPONSE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided modify request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeModifyRequest(final int messageID,
+ final ModifyRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP MODIFY REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_MODIFY_REQUEST);
+ writer.writeOctetString(request.getName().toString());
+
+ writer.writeStartSequence();
+ for (final Modification change : request.getModifications()) {
+ writeChange(change);
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided extended result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeModifyResult(final int messageID, final Result result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP MODIFY RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_MODIFY_RESPONSE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided search request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeSearchRequest(final int messageID,
+ final SearchRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP SEARCH REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_SEARCH_REQUEST);
+ writer.writeOctetString(request.getName().toString());
+ writer.writeEnumerated(request.getScope().intValue());
+ writer.writeEnumerated(request.getDereferenceAliasesPolicy().intValue());
+ writer.writeInteger(request.getSizeLimit());
+ writer.writeInteger(request.getTimeLimit());
+ writer.writeBoolean(request.isTypesOnly());
+ LDAPUtils.encodeFilter(writer, request.getFilter());
+
+ writer.writeStartSequence();
+ for (final String attribute : request.getAttributes()) {
+ writer.writeOctetString(attribute);
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write the provided search result.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param result
+ * the result
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeSearchResult(final int messageID, final Result result)
+ throws IOException {
+ IO_LOG.trace("ENCODE LDAP SEARCH RESULT(messageID={}, result={})", messageID, result);
+ writeMessageHeader(messageID);
+ writeResultHeader(OP_TYPE_SEARCH_RESULT_DONE, result);
+ writeResultFooter(writer);
+ writeMessageFooter(result);
+ }
+
+ /**
+ * Write the provided search result entry.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param entry
+ * the entry
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeSearchResultEntry(final int messageID,
+ final SearchResultEntry entry) throws IOException {
+ IO_LOG.trace("ENCODE LDAP SEARCH RESULT ENTRY(messageID={}, entry={})", messageID, entry);
+ writeMessageHeader(messageID);
+ writeEntry(entry);
+ writeMessageFooter(entry);
+ }
+
+ /**
+ * Write the provided search result reference.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param reference
+ * the reference
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeSearchResultReference(final int messageID,
+ final SearchResultReference reference) throws IOException {
+ IO_LOG.trace("ENCODE LDAP SEARCH RESULT REFERENCE(messageID={}, reference={})", messageID, reference);
+ writeMessageHeader(messageID);
+ writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
+ for (final String url : reference.getURIs()) {
+ writer.writeOctetString(url);
+ }
+ writer.writeEndSequence();
+ writeMessageFooter(reference);
+ }
+
+ /**
+ * Write the provided unbind request.
+ *
+ * @param messageID
+ * identifier of the request message
+ * @param request
+ * the request
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeUnbindRequest(final int messageID,
+ final UnbindRequest request) throws IOException {
+ IO_LOG.trace("ENCODE LDAP UNBIND REQUEST(messageID={}, request={})", messageID, request);
+ writeMessageHeader(messageID);
+ writer.writeNull(OP_TYPE_UNBIND_REQUEST);
+ writeMessageFooter(request);
+ }
+
+ /**
+ * Write a message with the provided id, tag and content bytes.
+ *
+ * @param messageID
+ * identifier of the result message
+ * @param messageTag
+ * tag identifying the type of message
+ * @param messageBytes
+ * content of message
+ * @throws IOException
+ * if an error occurs during write operation
+ */
+ public void writeUnrecognizedMessage(final int messageID,
+ final byte messageTag, final ByteString messageBytes) throws IOException {
+ IO_LOG.trace("ENCODE LDAP UNKNOWN MESSAGE(messageID={}, messageTag={}, messageBytes={})",
+ messageID, StaticUtils.byteToHex(messageTag), messageBytes);
+ writeMessageHeader(messageID);
+ writer.writeOctetString(messageTag, messageBytes);
+ writer.writeEndSequence();
+ }
+}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/package-info.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/package-info.java
new file mode 100644
index 0000000..d00f4bd
--- /dev/null
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/io/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Classes providing I/O functionality.
+ */
+package org.forgerock.opendj.io;
+
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/TimeoutChecker.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutChecker.java
similarity index 70%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/TimeoutChecker.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutChecker.java
index 7cf8bfc..943cdd9 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/TimeoutChecker.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutChecker.java
@@ -25,7 +25,7 @@
* Portions copyright 2013 ForgeRock AS.
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.ldap;
import static com.forgerock.opendj.util.StaticUtils.DEFAULT_LOG;
import static java.util.Collections.newSetFromMap;
@@ -35,13 +35,19 @@
import com.forgerock.opendj.util.ReferenceCountedObject;
/**
- * Checks connection for pending requests that have timed out.
+ * Checks {@code TimeoutEventListener listeners} for events that have timed out.
+ * <p>
+ * All listeners registered with the {@code #addListener()} method are called
+ * back with {@code TimeoutEventListener#handleTimeout()} to be able to handle
+ * the timeout.
+ * <p>
+ *
*/
-final class TimeoutChecker {
+public final class TimeoutChecker {
/**
- * Global reference counted instance.
+ * Global reference on the timeout checker.
*/
- static final ReferenceCountedObject<TimeoutChecker> TIMEOUT_CHECKER =
+ public static final ReferenceCountedObject<TimeoutChecker> TIMEOUT_CHECKER =
new ReferenceCountedObject<TimeoutChecker>() {
@Override
protected void destroyInstance(final TimeoutChecker instance) {
@@ -60,11 +66,12 @@
private final Object available = new Object();
/**
- * The connection set must be safe from CMEs because expiring requests can
+ * The listener set must be safe from CMEs.
+ * For example, if the listener is a connection, expiring requests can
* cause the connection to be closed.
*/
- private final Set<GrizzlyLDAPConnection> connections =
- newSetFromMap(new ConcurrentHashMap<GrizzlyLDAPConnection, Boolean>());
+ private final Set<TimeoutEventListener> listeners =
+ newSetFromMap(new ConcurrentHashMap<TimeoutEventListener, Boolean>());
/**
* Used to signal thread shutdown.
@@ -72,19 +79,18 @@
private volatile boolean shutdownRequested = false;
private TimeoutChecker() {
- final Thread checkerThread = new Thread("OpenDJ LDAP SDK Connection Timeout Checker") {
+ final Thread checkerThread = new Thread("OpenDJ LDAP SDK Timeout Checker") {
@Override
public void run() {
DEFAULT_LOG.debug("Timeout Checker Starting");
while (!shutdownRequested) {
final long currentTime = System.currentTimeMillis();
long delay = 0;
-
- for (final GrizzlyLDAPConnection connection : connections) {
- DEFAULT_LOG.trace("Checking connection {} delay = {}", connection, delay);
+ for (final TimeoutEventListener listener : listeners) {
+ DEFAULT_LOG.trace("Checking connection {} delay = {}", listener, delay);
// May update the connections set.
- final long newDelay = connection.cancelExpiredRequests(currentTime);
+ final long newDelay = listener.handleTimeout(currentTime);
if (newDelay > 0) {
if (delay > 0) {
delay = Math.min(newDelay, delay);
@@ -113,13 +119,27 @@
checkerThread.start();
}
- void addConnection(final GrizzlyLDAPConnection connection) {
- connections.add(connection);
- signal();
+ /**
+ * Add a listener to check.
+ *
+ * @param listener
+ * listener to check for timeout event
+ */
+ public void addListener(final TimeoutEventListener listener) {
+ listeners.add(listener);
+ if (listener.getTimeout() > 0) {
+ signal();
+ }
}
- void removeConnection(final GrizzlyLDAPConnection connection) {
- connections.remove(connection);
+ /**
+ * Stop checking a listener.
+ *
+ * @param listener
+ * listener that was previously added to check for timeout event
+ */
+ public void removeListener(final TimeoutEventListener listener) {
+ listeners.remove(listener);
// No need to signal.
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutEventListener.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutEventListener.java
new file mode 100644
index 0000000..d67b385
--- /dev/null
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutEventListener.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.forgerock.opendj.ldap;
+
+/**
+ * Listener on timeout events.
+ * <p>
+ * The listener must register itself with a {@code TimeoutChecker} using
+ * {@code TimeoutChecker#addListener()} method to be called back with
+ * {@code #handleTimeout} method.
+ * <p>
+ * The listener must deregister itself using
+ * {@code TimeoutChecker#removeListener()} to stop being called back.
+ */
+public interface TimeoutEventListener {
+
+ /**
+ * Handle a timeout event.
+ *
+ * @param currentTime
+ * time to use as current time for any check
+ * @return the delay to wait before next timeout callback in milliseconds
+ */
+ long handleTimeout(final long currentTime);
+
+ /**
+ * Returns the timeout for this listener.
+ *
+ * @return the timeout in milliseconds
+ */
+ long getTimeout();
+
+}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/AbstractLDAPMessageHandler.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/AbstractLDAPMessageHandler.java
similarity index 63%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/AbstractLDAPMessageHandler.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/AbstractLDAPMessageHandler.java
index d653fcc..8d848f9 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/AbstractLDAPMessageHandler.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/AbstractLDAPMessageHandler.java
@@ -22,9 +22,10 @@
*
*
* Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.ldap.spi;
import java.io.IOException;
@@ -48,119 +49,140 @@
import org.forgerock.opendj.ldap.responses.SearchResultReference;
/**
- * Abstract LDAP message handler.
- *
- * @param <P>
- * A user provided handler parameter.
+ * Provides a LDAPMessageHandler implementation that throw an exception for all
+ * methods.
*/
-abstract class AbstractLDAPMessageHandler<P> implements LDAPMessageHandler<P> {
- public void abandonRequest(final P param, final int messageID, final AbandonRequest request)
+public abstract class AbstractLDAPMessageHandler implements LDAPMessageHandler {
+
+ @Override
+ public void abandonRequest(final int messageID, final AbandonRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void addRequest(final P param, final int messageID, final AddRequest request)
+ @Override
+ public void addRequest(final int messageID, final AddRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void addResult(final P param, final int messageID, final Result result)
+ @Override
+ public void addResult(final int messageID, final Result result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void bindRequest(final P param, final int messageID, final int version,
- final GenericBindRequest request) throws UnexpectedRequestException, IOException {
- throw new UnexpectedRequestException(messageID, request);
- }
-
- public void bindResult(final P param, final int messageID, final BindResult result)
- throws UnexpectedResponseException, IOException {
- throw new UnexpectedResponseException(messageID, result);
- }
-
- public void compareRequest(final P param, final int messageID, final CompareRequest request)
+ @Override
+ public void bindRequest(final int messageID, final int version, final GenericBindRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void compareResult(final P param, final int messageID, final CompareResult result)
+ @Override
+ public void bindResult(final int messageID, final BindResult result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void deleteRequest(final P param, final int messageID, final DeleteRequest request)
+ @Override
+ public void compareRequest(final int messageID, final CompareRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void deleteResult(final P param, final int messageID, final Result result)
+ @Override
+ public void compareResult(final int messageID, final CompareResult result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public <R extends ExtendedResult> void extendedRequest(final P param, final int messageID,
- final ExtendedRequest<R> request) throws UnexpectedRequestException, IOException {
+ @Override
+ public void deleteRequest(final int messageID, final DeleteRequest request)
+ throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void extendedResult(final P param, final int messageID, final ExtendedResult result)
+ @Override
+ public void deleteResult(final int messageID, final Result result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void intermediateResponse(final P param, final int messageID,
- final IntermediateResponse response) throws UnexpectedResponseException, IOException {
+ @Override
+ public <R extends ExtendedResult> void extendedRequest(final int messageID, final ExtendedRequest<R> request)
+ throws UnexpectedRequestException, IOException {
+ throw new UnexpectedRequestException(messageID, request);
+ }
+
+ @Override
+ public void extendedResult(final int messageID, final ExtendedResult result)
+ throws UnexpectedResponseException, IOException {
+ throw new UnexpectedResponseException(messageID, result);
+ }
+
+ @Override
+ public void intermediateResponse(final int messageID, final IntermediateResponse response)
+ throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, response);
}
- public void modifyDNRequest(final P param, final int messageID, final ModifyDNRequest request)
+ @Override
+ public void modifyDNRequest(final int messageID, final ModifyDNRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void modifyDNResult(final P param, final int messageID, final Result result)
+ @Override
+ public void modifyDNResult(final int messageID, final Result result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void modifyRequest(final P param, final int messageID, final ModifyRequest request)
+ @Override
+ public void modifyRequest(final int messageID, final ModifyRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void modifyResult(final P param, final int messageID, final Result result)
+ @Override
+ public void modifyResult(final int messageID, final Result result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void searchRequest(final P param, final int messageID, final SearchRequest request)
+ @Override
+ public void searchRequest(final int messageID, final SearchRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void searchResult(final P param, final int messageID, final Result result)
+ @Override
+ public void searchResult(final int messageID, final Result result)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, result);
}
- public void searchResultEntry(final P param, final int messageID, final SearchResultEntry entry)
+ @Override
+ public void searchResultEntry(final int messageID, final SearchResultEntry entry)
throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, entry);
}
- public void searchResultReference(final P param, final int messageID,
- final SearchResultReference reference) throws UnexpectedResponseException, IOException {
+ @Override
+ public void searchResultReference(final int messageID, final SearchResultReference reference)
+ throws UnexpectedResponseException, IOException {
throw new UnexpectedResponseException(messageID, reference);
}
- public void unbindRequest(final P param, final int messageID, final UnbindRequest request)
+ @Override
+ public void unbindRequest(final int messageID, final UnbindRequest request)
throws UnexpectedRequestException, IOException {
throw new UnexpectedRequestException(messageID, request);
}
- public void unrecognizedMessage(final P param, final int messageID, final byte messageTag,
- final ByteString messageBytes) throws UnsupportedMessageException, IOException {
+ @Override
+ public void unrecognizedMessage(final int messageID, final byte messageTag, final ByteString messageBytes)
+ throws UnsupportedMessageException, IOException {
throw new UnsupportedMessageException(messageID, messageTag, messageBytes);
}
}
diff --git a/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPMessageHandler.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPMessageHandler.java
new file mode 100644
index 0000000..3ddf76a
--- /dev/null
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPMessageHandler.java
@@ -0,0 +1,392 @@
+/*
+ * 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 2009 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.ldap.spi;
+
+import java.io.IOException;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.requests.AbandonRequest;
+import org.forgerock.opendj.ldap.requests.AddRequest;
+import org.forgerock.opendj.ldap.requests.CompareRequest;
+import org.forgerock.opendj.ldap.requests.DeleteRequest;
+import org.forgerock.opendj.ldap.requests.ExtendedRequest;
+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.SearchRequest;
+import org.forgerock.opendj.ldap.requests.UnbindRequest;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.CompareResult;
+import org.forgerock.opendj.ldap.responses.ExtendedResult;
+import org.forgerock.opendj.ldap.responses.IntermediateResponse;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.opendj.ldap.responses.SearchResultReference;
+
+/**
+ * Interface for handler of LDAP messages (requests and responses).
+ *
+ */
+public interface LDAPMessageHandler {
+
+ /**
+ * Handle an abandon request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * abandon request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void abandonRequest(int messageID, AbandonRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle an add request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * add request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void addRequest(int messageID, AddRequest request) throws UnexpectedRequestException,
+ IOException;
+
+ /**
+ * Handle a response to an add request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void addResult(int messageID, Result result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle a bind request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param version
+ * protocol version for this bind request
+ * @param request
+ * bind request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void bindRequest(int messageID, int version, GenericBindRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a bind request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void bindResult(int messageID, BindResult result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle a compare request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * compare request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void compareRequest(int messageID, CompareRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a compare request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void compareResult(int messageID, CompareResult result)
+ throws UnexpectedResponseException, IOException;
+
+ /**
+ * Handle an delete request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * delete request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void deleteRequest(int messageID, DeleteRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a delete request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void deleteResult(int messageID, Result result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle an extended request.
+ *
+ * @param <R>
+ * type of extended result
+ * @param messageID
+ * identifier of message
+ * @param request
+ * extended request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ <R extends ExtendedResult> void extendedRequest(int messageID, ExtendedRequest<R> request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to an extended request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void extendedResult(int messageID, ExtendedResult result)
+ throws UnexpectedResponseException, IOException;
+
+ /**
+ * Handle an intermediate response.
+ *
+ * @param messageID
+ * identifier of message
+ * @param response
+ * intermediate response to handle
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void intermediateResponse(int messageID, IntermediateResponse response)
+ throws UnexpectedResponseException, IOException;
+
+ /**
+ * Handle a modify DN request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * modify DN request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void modifyDNRequest(int messageID, ModifyDNRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a modify DN request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void modifyDNResult(int messageID, Result result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle a modify request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * modify request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void modifyRequest(int messageID, ModifyRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a modify request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void modifyResult(int messageID, Result result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle a search request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * search request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void searchRequest(int messageID, SearchRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle a response to a search request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param result
+ * response received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void searchResult(int messageID, Result result) throws UnexpectedResponseException,
+ IOException;
+
+ /**
+ * Handle a response to a search request returning an entry.
+ *
+ * @param messageID
+ * identifier of message
+ * @param entry
+ * entry received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void searchResultEntry(int messageID, SearchResultEntry entry)
+ throws UnexpectedResponseException, IOException;
+
+ /**
+ * Handle a response to a search request returning an reference.
+ *
+ * @param messageID
+ * identifier of message
+ * @param reference
+ * reference received
+ * @throws UnexpectedResponseException
+ * if response is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void searchResultReference(int messageID, SearchResultReference reference)
+ throws UnexpectedResponseException, IOException;
+
+ /**
+ * Handle an unbind request.
+ *
+ * @param messageID
+ * identifier of message
+ * @param request
+ * unbind request to handle
+ * @throws UnexpectedRequestException
+ * if request is not expected by this handler
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void unbindRequest(int messageID, UnbindRequest request)
+ throws UnexpectedRequestException, IOException;
+
+ /**
+ * Handle an unrecognized message.
+ *
+ * @param messageID
+ * identifier of message
+ * @param messageTag
+ * tag identifying the message type
+ * @param messageBytes
+ * content of the message
+ * @throws UnsupportedMessageException
+ * if the received message is not supported
+ * @throws IOException
+ * if an errors occurs when sending a subsequent message
+ */
+ void unrecognizedMessage(int messageID, byte messageTag, ByteString messageBytes)
+ throws UnsupportedMessageException, IOException;
+}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedRequestException.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedRequestException.java
similarity index 72%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedRequestException.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedRequestException.java
index 368b264..2d01713 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedRequestException.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedRequestException.java
@@ -22,9 +22,10 @@
*
*
* Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.ldap.spi;
import java.io.IOException;
@@ -32,13 +33,21 @@
import org.forgerock.opendj.ldap.requests.Request;
/**
- * Thrown when an expected LDAP request is received.
+ * Thrown when an unexpected LDAP request is received.
*/
@SuppressWarnings("serial")
-final class UnexpectedRequestException extends IOException {
+public final class UnexpectedRequestException extends IOException {
private final int messageID;
private final Request request;
+ /**
+ * Creates the exception with a message id and a request.
+ *
+ * @param messageID
+ * id of message
+ * @param request
+ * request received
+ */
public UnexpectedRequestException(final int messageID, final Request request) {
super(LocalizableMessage.raw("Unexpected LDAP request: id=%d, message=%s", messageID,
request).toString());
@@ -46,10 +55,20 @@
this.request = request;
}
+ /**
+ * Returns the identifier of the message.
+ *
+ * @return the identifier
+ */
public int getMessageID() {
return messageID;
}
+ /**
+ * Returns the request.
+ *
+ * @return the received request
+ */
public Request getRequest() {
return request;
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedResponseException.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedResponseException.java
similarity index 74%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedResponseException.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedResponseException.java
index a386fd7..2f1b02d 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedResponseException.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnexpectedResponseException.java
@@ -22,9 +22,10 @@
*
*
* Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.ldap.spi;
import java.io.IOException;
@@ -35,10 +36,18 @@
* Thrown when an unexpected LDAP response is received.
*/
@SuppressWarnings("serial")
-final class UnexpectedResponseException extends IOException {
+public final class UnexpectedResponseException extends IOException {
private final int messageID;
private final Response response;
+ /**
+ * Creates the exception with a message id and a response.
+ *
+ * @param messageID
+ * id of message
+ * @param response
+ * response received
+ */
public UnexpectedResponseException(final int messageID, final Response response) {
super(LocalizableMessage.raw("Unexpected LDAP response: id=%d, message=%s", messageID,
response).toString());
@@ -46,10 +55,20 @@
this.response = response;
}
+ /**
+ * Returns the identifier of the message.
+ *
+ * @return the identifier
+ */
public int getMessageID() {
return messageID;
}
+ /**
+ * Returns the response.
+ *
+ * @return the received response
+ */
public Response getResponse() {
return response;
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnsupportedMessageException.java b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnsupportedMessageException.java
similarity index 71%
rename from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnsupportedMessageException.java
rename to opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnsupportedMessageException.java
index 129ec01..1dc337d 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnsupportedMessageException.java
+++ b/opendj3/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/UnsupportedMessageException.java
@@ -22,9 +22,10 @@
*
*
* Copyright 2009 Sun Microsystems, Inc.
+ * Portions copyright 2013 ForgeRock AS.
*/
-package com.forgerock.opendj.grizzly;
+package org.forgerock.opendj.ldap.spi;
import java.io.IOException;
@@ -35,11 +36,21 @@
* Thrown when an unsupported LDAP message is received.
*/
@SuppressWarnings("serial")
-final class UnsupportedMessageException extends IOException {
+public final class UnsupportedMessageException extends IOException {
private final int id;
private final byte tag;
private final ByteString content;
+ /**
+ * Creates the exception with message id, tag and content.
+ *
+ * @param id
+ * identifier of received message
+ * @param tag
+ * identify message type
+ * @param content
+ * message content
+ */
public UnsupportedMessageException(final int id, final byte tag, final ByteString content) {
super(LocalizableMessage.raw("Unsupported LDAP message: id=%d, tag=%d, content=%s", id,
tag, content).toString());
@@ -48,14 +59,29 @@
this.content = content;
}
+ /**
+ * Returns the content.
+ *
+ * @return the message content
+ */
public ByteString getContent() {
return content;
}
+ /**
+ * Returns the id.
+ *
+ * @return the message identifier
+ */
public int getID() {
return id;
}
+ /**
+ * Returns the tag.
+ *
+ * @return the message tag
+ */
public byte getTag() {
return tag;
}
diff --git a/opendj3/opendj-core/src/test/java/org/forgerock/opendj/io/LDAPReaderWriterTestCase.java b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/io/LDAPReaderWriterTestCase.java
new file mode 100644
index 0000000..65c7ded
--- /dev/null
+++ b/opendj3/opendj-core/src/test/java/org/forgerock/opendj/io/LDAPReaderWriterTestCase.java
@@ -0,0 +1,178 @@
+/*
+ * 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 org.forgerock.opendj.io;
+
+import static org.fest.assertions.Assertions.*;
+
+import java.io.IOException;
+
+import org.forgerock.opendj.asn1.ASN1Reader;
+import org.forgerock.opendj.asn1.ASN1Writer;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SdkTestCase;
+import org.forgerock.opendj.ldap.requests.AbandonRequest;
+import org.forgerock.opendj.ldap.requests.AddRequest;
+import org.forgerock.opendj.ldap.requests.GenericBindRequest;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.Responses;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldap.spi.AbstractLDAPMessageHandler;
+import org.forgerock.opendj.ldap.spi.LDAPMessageHandler;
+import org.forgerock.opendj.ldap.spi.UnexpectedRequestException;
+import org.forgerock.opendj.ldap.spi.UnexpectedResponseException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Support class for testing {@code LDAPWriter} and {@code LDAPReader}
+ * classes in a specific transport provider.
+ *
+ * A specific transport provider should provide a test case by :
+ * <ul>
+ * <li>Extending this class</li>
+ * <li>Implementing the 3 abstract methods {@code getLDAPReader()}, {@code getLDAPReader()}
+ * and {@code transferFromWriterToReader()}</li>
+ * </ul>
+ */
+public abstract class LDAPReaderWriterTestCase extends SdkTestCase {
+
+ // DN used is several tests
+ private static final String TEST_DN = "cn=test";
+
+ interface LDAPWrite {
+ public void perform(LDAPWriter<? extends ASN1Writer> writer) throws IOException;
+ }
+
+ @DataProvider
+ protected Object[][] messagesFactories() {
+ return new Object[][] {
+ addRequest(),
+ addResult(),
+ abandonRequest(),
+ bindRequest(),
+ };
+ }
+
+ Object[] addRequest() {
+ return new Object[] { new LDAPWrite() {
+ @Override
+ public void perform(LDAPWriter<? extends ASN1Writer> writer) throws IOException {
+ writer.writeAddRequest(0, Requests.newAddRequest(TEST_DN));
+ }
+ }, new AbstractLDAPMessageHandler() {
+ @Override
+ public void addRequest(int messageID, AddRequest request) throws UnexpectedRequestException, IOException {
+ assertThat(request.getName().toString()).isEqualTo(TEST_DN);
+ }
+ } };
+ }
+
+ Object[] addResult() {
+ final ResultCode resultCode = ResultCode.SUCCESS;
+ return new Object[] { new LDAPWrite() {
+ @Override
+ public void perform(LDAPWriter<? extends ASN1Writer> writer) throws IOException {
+ writer.writeAddResult(1, Responses.newResult(resultCode).setMatchedDN(TEST_DN));
+ }
+ }, new AbstractLDAPMessageHandler() {
+ @Override
+ public void addResult(int messageID, Result result) throws UnexpectedResponseException, IOException {
+ assertThat(result.getResultCode()).isEqualTo(resultCode);
+ assertThat(result.getMatchedDN().toString()).isEqualTo(TEST_DN);
+ }
+ } };
+ }
+
+ Object[] abandonRequest() {
+ final int requestID = 1;
+ return new Object[] { new LDAPWrite() {
+ @Override
+ public void perform(LDAPWriter<? extends ASN1Writer> writer) throws IOException {
+ writer.writeAbandonRequest(0, Requests.newAbandonRequest(requestID));
+ }
+ }, new AbstractLDAPMessageHandler() {
+ @Override
+ public void abandonRequest(int messageID, AbandonRequest request) throws UnexpectedRequestException,
+ IOException {
+ assertThat(request.getRequestID()).isEqualTo(requestID);
+ }
+ } };
+ }
+
+ Object[] bindRequest() {
+ final byte type = 0x01;
+ final byte[] value = new byte[] {0x01, 0x02};
+ return new Object[] { new LDAPWrite() {
+ @Override
+ public void perform(LDAPWriter<? extends ASN1Writer> writer) throws IOException {
+ writer.writeBindRequest(0, 1,
+ Requests.newGenericBindRequest(TEST_DN, type, value));
+ }
+ }, new AbstractLDAPMessageHandler() {
+ @Override
+ public void bindRequest(final int messageID, final int version, final GenericBindRequest request)
+ throws UnexpectedRequestException, IOException {
+ assertThat(request.getAuthenticationType()).isEqualTo(type);
+ assertThat(request.getAuthenticationValue()).isEqualTo(value);
+ assertThat(request.getName()).isEqualTo(TEST_DN);
+ }
+ } };
+ }
+
+ /**
+ * Test that a LDAP message written by LDAPWriter is read correctly using LDAPReader.
+ *
+ * @param writing write instruction to perform
+ * @param messageHandler handler of message read, containing assertion
+ *
+ * @throws Exception
+ */
+ @Test(dataProvider = "messagesFactories")
+ public void testWriteReadMessage(LDAPWrite writing, LDAPMessageHandler messageHandler)
+ throws Exception {
+ LDAPWriter<? extends ASN1Writer> writer = getLDAPWriter();
+ writing.perform(writer);
+ LDAPReader<? extends ASN1Reader> reader = getLDAPReader();
+ transferFromWriterToReader(writer, reader);
+ reader.readMessage(messageHandler);
+ }
+
+ /**
+ * Returns a writer specific to the transport module.
+ */
+ abstract protected LDAPWriter<? extends ASN1Writer> getLDAPWriter();
+
+ /**
+ * Returns a reader specific to the transport module.
+ */
+ abstract protected LDAPReader<? extends ASN1Reader> getLDAPReader();
+
+ /**
+ * Transfer raw data from writer to the reader.
+ */
+ abstract protected void transferFromWriterToReader(LDAPWriter<? extends ASN1Writer> writer,
+ LDAPReader<? extends ASN1Reader> reader);
+}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferReader.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferReader.java
index c2c12f8..ce6ead2 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferReader.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferReader.java
@@ -27,15 +27,12 @@
package com.forgerock.opendj.grizzly;
-import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
-import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
-import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_TYPE;
-import static com.forgerock.opendj.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_VALUE_BYTES;
import static com.forgerock.opendj.ldap.CoreMessages.*;
-import static com.forgerock.opendj.util.StaticUtils.IO_LOG;
-import static com.forgerock.opendj.util.StaticUtils.byteToHex;
+import static com.forgerock.opendj.ldap.LDAPConstants.*;
+import static com.forgerock.opendj.util.StaticUtils.*;
import java.io.IOException;
+
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.asn1.ASN1Reader;
import org.forgerock.opendj.asn1.AbstractASN1Reader;
@@ -50,7 +47,7 @@
/**
* Grizzly ASN1 reader implementation.
*/
-final class ASN1BufferReader extends AbstractASN1Reader implements ASN1Reader {
+final class ASN1BufferReader extends AbstractASN1Reader {
private final class ChildSequenceLimiter implements SequenceLimiter {
private SequenceLimiter parent;
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferWriter.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferWriter.java
index 82fff73..18f652b 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferWriter.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/ASN1BufferWriter.java
@@ -40,7 +40,6 @@
import org.forgerock.opendj.ldap.ByteStringBuilder;
import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Cacheable;
-import org.glassfish.grizzly.ThreadCache;
import org.glassfish.grizzly.memory.ByteBufferWrapper;
import com.forgerock.opendj.util.StaticUtils;
@@ -48,7 +47,7 @@
/**
* Grizzly ASN1 writer implementation.
*/
-final class ASN1BufferWriter extends AbstractASN1Writer implements ASN1Writer, Cacheable {
+final class ASN1BufferWriter extends AbstractASN1Writer implements Cacheable {
private class ChildSequenceBuffer implements SequenceBuffer {
private SequenceBuffer parent;
@@ -162,21 +161,16 @@
}
private static final int BUFFER_INIT_SIZE = 1024;
- private final static ThreadCache.CachedTypeIndex<ASN1BufferWriter> WRITER_INDEX = ThreadCache
- .obtainIndex(ASN1BufferWriter.class, 1);
- static ASN1BufferWriter getWriter() {
- ASN1BufferWriter asn1Writer = ThreadCache.takeFromCache(WRITER_INDEX);
- if (asn1Writer == null) {
- asn1Writer = new ASN1BufferWriter();
- }
-
- if (!asn1Writer.outBuffer.usable) {
+ /**
+ * Reset the writer.
+ */
+ void reset() {
+ if (!outBuffer.usable) {
// If the output buffer is unusable, create a new one.
- asn1Writer.outBuffer = new RecyclableBuffer();
+ outBuffer = new RecyclableBuffer();
}
- asn1Writer.outBuffer.clear();
- return asn1Writer;
+ outBuffer.clear();
}
private SequenceBuffer sequenceBuffer;
@@ -187,7 +181,7 @@
/**
* Creates a new ASN.1 writer that writes to a StreamWriter.
*/
- private ASN1BufferWriter() {
+ ASN1BufferWriter() {
this.sequenceBuffer = this.rootBuffer = new RootSequenceBuffer();
this.outBuffer = new RecyclableBuffer();
}
@@ -213,10 +207,12 @@
// Do nothing
}
+ /**
+ * Recycle the writer to allow re-use.
+ */
public void recycle() {
sequenceBuffer = rootBuffer;
outBuffer.clear();
- ThreadCache.putToCache(WRITER_INDEX, this);
}
/**
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
index 6a2f5d8..c348a33 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
@@ -44,8 +44,8 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
+import org.forgerock.opendj.io.LDAPWriter;
import org.forgerock.opendj.ldap.AbstractAsynchronousConnection;
-import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.ConnectionEventListener;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.FutureResult;
@@ -55,6 +55,7 @@
import org.forgerock.opendj.ldap.ResultHandler;
import org.forgerock.opendj.ldap.SSLContextBuilder;
import org.forgerock.opendj.ldap.SearchResultHandler;
+import org.forgerock.opendj.ldap.TimeoutEventListener;
import org.forgerock.opendj.ldap.TrustManagers;
import org.forgerock.opendj.ldap.requests.AbandonRequest;
import org.forgerock.opendj.ldap.requests.AddRequest;
@@ -93,7 +94,7 @@
/**
* LDAP connection implementation.
*/
-final class GrizzlyLDAPConnection extends AbstractAsynchronousConnection implements Connection {
+final class GrizzlyLDAPConnection extends AbstractAsynchronousConnection implements TimeoutEventListener {
/**
* A dummy SSL client engine configurator as SSLFilter only needs client
* config. This prevents Grizzly from needlessly using JVM defaults which
@@ -113,7 +114,6 @@
private final AtomicBoolean bindOrStartTLSInProgress = new AtomicBoolean(false);
private final org.glassfish.grizzly.Connection<?> connection;
- private final LDAPWriter ldapWriter = new LDAPWriter();
private final AtomicInteger nextMsgID = new AtomicInteger(1);
private final GrizzlyLDAPConnectionFactory factory;
private final ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>> pendingRequests =
@@ -126,6 +126,15 @@
private boolean isFailed = false;
private List<ConnectionEventListener> listeners = null;
+ /**
+ * Create a LDAP Connection with provided Grizzly connection and LDAP
+ * connection factory.
+ *
+ * @param connection
+ * actual connection
+ * @param factory
+ * factory that provides LDAP connections
+ */
GrizzlyLDAPConnection(final org.glassfish.grizzly.Connection<?> connection,
final GrizzlyLDAPConnectionFactory factory) {
this.connection = connection;
@@ -155,13 +164,13 @@
}
pendingRequest.cancel(false);
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.abandonRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeAbandonRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
return new CompletedFutureResult<Void>((Void) null, messageID);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
throw adaptRequestIOException(e);
@@ -186,12 +195,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.addRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeAddRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -275,15 +284,15 @@
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
// Use the bind client to get the initial request instead of
// using the bind request passed to this method.
final GenericBindRequest initialRequest = context.nextBindRequest();
- ldapWriter.bindRequest(asn1Writer, messageID, 3, initialRequest);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeBindRequest(messageID, 3, initialRequest);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -320,12 +329,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.compareRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeCompareRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -352,12 +361,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.deleteRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeDeleteRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -404,12 +413,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.extendedRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeExtendedRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -451,12 +460,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.modifyRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeModifyRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -483,12 +492,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.modifyDNRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeModifyDNRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -525,12 +534,12 @@
pendingRequests.put(messageID, future);
}
try {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.searchRequest(asn1Writer, messageID, request);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeSearchRequest(messageID, request);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
} catch (final IOException e) {
pendingRequests.remove(messageID);
@@ -553,19 +562,26 @@
return builder.toString();
}
- long cancelExpiredRequests(final long currentTime) {
- final long timeout = factory.getLDAPOptions().getTimeout(TimeUnit.MILLISECONDS);
+ @Override
+ public long handleTimeout(final long currentTime) {
+ final long timeout = getTimeout();
long delay = timeout;
if (timeout > 0) {
for (final int requestID : pendingRequests.keySet()) {
final AbstractLDAPFutureResultImpl<?> future = pendingRequests.get(requestID);
if (future != null && future.checkForTimeout()) {
final long diff = (future.getTimestamp() + timeout) - currentTime;
- if (diff <= 0 && pendingRequests.remove(requestID) != null) {
- DEFAULT_LOG.debug("Cancelling expired future result: {}", future);
- final Result result = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT);
- future.adaptErrorResult(result);
- abandonAsync(Requests.newAbandonRequest(future.getRequestID()));
+ if (diff <= 0) {
+ if (pendingRequests.remove(requestID) != null) {
+ DEFAULT_LOG.debug("Cancelling expired future result: {}", future);
+ final Result result = Responses.newResult(ResultCode.CLIENT_SIDE_TIMEOUT);
+ future.adaptErrorResult(result);
+ abandonAsync(Requests.newAbandonRequest(future.getRequestID()));
+ } else {
+ DEFAULT_LOG.debug(
+ "Pending request {} has already been removed, not cancelling future result",
+ requestID);
+ }
} else {
delay = Math.min(delay, diff);
}
@@ -575,6 +591,11 @@
return delay;
}
+ @Override
+ public long getTimeout() {
+ return factory.getLDAPOptions().getTimeout(TimeUnit.MILLISECONDS);
+ }
+
/**
* Closes this connection, invoking event listeners as needed.
*
@@ -633,19 +654,19 @@
* connection and release resources.
*/
if (notifyClose) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- ldapWriter.unbindRequest(asn1Writer, nextMsgID.getAndIncrement(), unbindRequest);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeUnbindRequest(nextMsgID.getAndIncrement(), unbindRequest);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} catch (final Exception ignore) {
/*
* Underlying channel probably blown up. Ignore all errors,
* including possibly runtime exceptions (see OPENDJ-672).
*/
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
- factory.getTimeoutChecker().removeConnection(this);
+ factory.getTimeoutChecker().removeListener(this);
connection.closeSilently();
factory.releaseTransportAndTimeoutChecker();
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java
index 165e400..4fa7811 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java
@@ -28,8 +28,8 @@
package com.forgerock.opendj.grizzly;
import static com.forgerock.opendj.grizzly.DefaultTCPNIOTransport.DEFAULT_TRANSPORT;
-import static com.forgerock.opendj.grizzly.TimeoutChecker.TIMEOUT_CHECKER;
import static org.forgerock.opendj.ldap.ErrorResultException.*;
+import static org.forgerock.opendj.ldap.TimeoutChecker.TIMEOUT_CHECKER;
import java.io.IOException;
import java.net.SocketAddress;
@@ -45,6 +45,7 @@
import org.forgerock.opendj.ldap.LDAPOptions;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.ResultHandler;
+import org.forgerock.opendj.ldap.TimeoutChecker;
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.StartTLSExtendedRequest;
import org.forgerock.opendj.ldap.responses.ExtendedResult;
@@ -165,7 +166,7 @@
connection.configureBlocking(true);
final GrizzlyLDAPConnection ldapConnection =
new GrizzlyLDAPConnection(connection, GrizzlyLDAPConnectionFactory.this);
- timeoutChecker.get().addConnection(ldapConnection);
+ timeoutChecker.get().addListener(ldapConnection);
clientFilter.registerConnection(connection, ldapConnection);
return ldapConnection;
}
@@ -254,7 +255,7 @@
this.transport = DEFAULT_TRANSPORT.acquireIfNull(transport);
this.socketAddress = address;
this.options = new LDAPOptions(options);
- this.clientFilter = new LDAPClientFilter(new LDAPReader(this.options.getDecodeOptions()), 0);
+ this.clientFilter = new LDAPClientFilter(this.options.getDecodeOptions(), 0);
this.defaultFilterChain = GrizzlyUtils.buildFilterChain(this.transport.get().getProcessor(), clientFilter);
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPListener.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPListener.java
index b441b64..e9748cd 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPListener.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyLDAPListener.java
@@ -102,7 +102,7 @@
this.connectionFactory = factory;
final DecodeOptions decodeOptions = new DecodeOptions(options.getDecodeOptions());
- final LDAPServerFilter serverFilter = new LDAPServerFilter(this, new LDAPReader(decodeOptions), options
+ final LDAPServerFilter serverFilter = new LDAPServerFilter(this, decodeOptions, options
.getMaxRequestSize());
final FilterChain ldapChain = GrizzlyUtils.buildFilterChain(this.transport.get().getProcessor(), serverFilter);
final TCPNIOBindingHandler bindingHandler =
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyUtils.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyUtils.java
index 4750bdd..d81e72f 100644
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyUtils.java
+++ b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyUtils.java
@@ -25,11 +25,16 @@
*/
package com.forgerock.opendj.grizzly;
+import org.forgerock.opendj.io.LDAPReader;
+import org.forgerock.opendj.io.LDAPWriter;
+import org.forgerock.opendj.ldap.DecodeOptions;
import org.glassfish.grizzly.Processor;
+import org.glassfish.grizzly.ThreadCache;
import org.glassfish.grizzly.filterchain.Filter;
import org.glassfish.grizzly.filterchain.FilterChain;
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.TransportFilter;
+import org.glassfish.grizzly.memory.MemoryManager;
import org.glassfish.grizzly.ssl.SSLFilter;
/**
@@ -38,6 +43,10 @@
final class GrizzlyUtils {
+ @SuppressWarnings("rawtypes")
+ private static final ThreadCache.CachedTypeIndex<LDAPWriter> WRITER_INDEX = ThreadCache
+ .obtainIndex(LDAPWriter.class, 1);
+
/**
* Build a filter chain from the provided processor if possible and the
* provided filter.
@@ -57,7 +66,7 @@
* is a {@code FilterChain}, and having the provided filter as the
* last filter
*/
- public static FilterChain buildFilterChain(Processor processor, Filter filter) {
+ public static FilterChain buildFilterChain(Processor<?> processor, Filter filter) {
if (processor instanceof FilterChain) {
return FilterChainBuilder.stateless().addAll((FilterChain) processor).add(filter).build();
} else {
@@ -118,6 +127,57 @@
return FilterChainBuilder.stateless().addAll(chain).add(indexToAddFilter, filter).build();
}
+ /**
+ * Creates a new LDAP Reader with the provided maximum size of ASN1 element,
+ * options and memory manager.
+ *
+ * @param decodeOptions
+ * allow to control how responses and requests are decoded
+ * @param maxASN1ElementSize
+ * The maximum BER element size, or <code>0</code> to indicate
+ * that there is no limit.
+ * @param memoryManager
+ * The memory manager to use for buffering.
+ * @return a LDAP reader
+ */
+ public static LDAPReader<ASN1BufferReader> createReader(DecodeOptions decodeOptions, int maxASN1ElementSize,
+ MemoryManager<?> memoryManager) {
+ ASN1BufferReader asn1Reader = new ASN1BufferReader(maxASN1ElementSize, memoryManager);
+ return new LDAPReader<ASN1BufferReader>(asn1Reader, decodeOptions);
+ }
+
+ /**
+ * Returns a LDAP writer, with a clean ASN1Writer, possibly from
+ * the thread local cache.
+ * <p>
+ * The writer is either returned from thread local cache or created.
+ * In the former case, the writer is removed from the cache.
+ *
+ * @return a LDAP writer
+ */
+ @SuppressWarnings("unchecked")
+ public static LDAPWriter<ASN1BufferWriter> getWriter() {
+ LDAPWriter<ASN1BufferWriter> writer = ThreadCache.takeFromCache(WRITER_INDEX);
+ if (writer == null) {
+ writer = new LDAPWriter<ASN1BufferWriter>(new ASN1BufferWriter());
+ }
+ writer.getASN1Writer().reset();
+ return writer;
+ }
+
+ /**
+ * Recycle a LDAP writer to a thread local cache.
+ * <p>
+ * The LDAP writer is then available for the thread using the
+ * {@get()} method.
+ *
+ * @param writer LDAP writer to recycle
+ */
+ public static void recycleWriter(LDAPWriter<ASN1BufferWriter> writer) {
+ writer.getASN1Writer().recycle();
+ ThreadCache.putToCache(WRITER_INDEX, writer);
+ }
+
// Prevent instantiation.
private GrizzlyUtils() {
// No implementation required.
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 9b8ab08..a529127 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
@@ -34,8 +34,11 @@
import javax.net.ssl.SSLEngine;
+import org.forgerock.opendj.io.LDAPReader;
+import org.forgerock.opendj.io.LDAPWriter;
import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.AddRequest;
@@ -54,11 +57,13 @@
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
import org.forgerock.opendj.ldap.spi.AbstractLDAPFutureResultImpl;
+import org.forgerock.opendj.ldap.spi.AbstractLDAPMessageHandler;
import org.forgerock.opendj.ldap.spi.LDAPBindFutureResultImpl;
import org.forgerock.opendj.ldap.spi.LDAPCompareFutureResultImpl;
import org.forgerock.opendj.ldap.spi.LDAPExtendedFutureResultImpl;
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;
@@ -75,382 +80,413 @@
final class LDAPClientFilter extends BaseFilter {
private static final Attribute<GrizzlyLDAPConnection> LDAP_CONNECTION_ATTR =
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPClientConnection");
- private static final Attribute<ASN1BufferReader> LDAP_ASN1_READER_ATTR =
- Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPASN1Reader");
+
+ private static final Attribute<ClientResponseHandler> RESPONSE_HANDLER_ATTR =
+ Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("ClientResponseHandler");
private final int maxASN1ElementSize;
- private final LDAPReader ldapReader;
+ private final DecodeOptions decodeOptions;
- private static final AbstractLDAPMessageHandler<FilterChainContext> CLIENT_RESPONSE_HANDLER =
- new AbstractLDAPMessageHandler<FilterChainContext>() {
- @Override
- public void addResult(final FilterChainContext ctx, final int messageID,
- final Result result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
+ private static final class ClientResponseHandler extends AbstractLDAPMessageHandler {
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPFutureResultImpl) {
- final LDAPFutureResultImpl future =
- (LDAPFutureResultImpl) pendingRequest;
- if (future.getRequest() instanceof AddRequest) {
- future.setResultOrError(result);
- return;
- }
- }
- throw new UnexpectedResponseException(messageID, result);
+ private final LDAPReader<ASN1BufferReader> reader;
+ private FilterChainContext context;
+
+ /**
+ * Creates a handler with the provided reader.
+ *
+ * @param reader
+ * LDAP reader to use for reading incoming messages
+ */
+ public ClientResponseHandler(LDAPReader<ASN1BufferReader> reader) {
+ this.reader = reader;
+ }
+
+ void setFilterChainContext(FilterChainContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Returns the LDAP reader.
+ *
+ * @return the reader to read incoming LDAP messages
+ */
+ public LDAPReader<ASN1BufferReader> getReader() {
+ return this.reader;
+ }
+
+ @Override
+ public void addResult(final int messageID, final Result result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPFutureResultImpl) {
+ final LDAPFutureResultImpl future =
+ (LDAPFutureResultImpl) pendingRequest;
+ if (future.getRequest() instanceof AddRequest) {
+ future.setResultOrError(result);
+ return;
}
}
+ throw new UnexpectedResponseException(messageID, result);
}
+ }
+ }
- @Override
- public void bindResult(final FilterChainContext ctx, final int messageID,
- final BindResult result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
+ @Override
+ public void bindResult(final int messageID, final BindResult result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPBindFutureResultImpl) {
- final LDAPBindFutureResultImpl future =
- ((LDAPBindFutureResultImpl) pendingRequest);
- final BindClient bindClient = future.getBindClient();
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPBindFutureResultImpl) {
+ final LDAPBindFutureResultImpl future =
+ ((LDAPBindFutureResultImpl) pendingRequest);
+ final BindClient bindClient = future.getBindClient();
+ try {
+ if (!bindClient.evaluateResult(result)) {
+ // The server is expecting a multi stage
+ // bind response.
+ final int msgID =
+ ldapConnection.continuePendingBindRequest(future);
+
+ LDAPWriter<ASN1BufferWriter> ldapWriter = GrizzlyUtils.getWriter();
try {
- if (!bindClient.evaluateResult(result)) {
- // The server is expecting a multi stage
- // bind response.
- final int msgID =
- ldapConnection.continuePendingBindRequest(future);
-
- final ASN1BufferWriter asn1Writer =
- ASN1BufferWriter.getWriter();
- try {
- final GenericBindRequest nextRequest =
- bindClient.nextBindRequest();
- new LDAPWriter().bindRequest(asn1Writer, msgID, 3,
- nextRequest);
- ctx.write(asn1Writer.getBuffer(), null);
- } finally {
- asn1Writer.recycle();
- }
- return;
- }
- } catch (final ErrorResultException e) {
- ldapConnection.setBindOrStartTLSInProgress(false);
- future.adaptErrorResult(e.getResult());
- return;
- } catch (final IOException e) {
- // FIXME: I18N need to have a better error
- // message.
- // FIXME: Is this the best result code?
- ldapConnection.setBindOrStartTLSInProgress(false);
- final Result errorResult =
- Responses
- .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
- .setDiagnosticMessage(
- "An error occurred during multi-stage authentication")
- .setCause(e);
- future.adaptErrorResult(errorResult);
- return;
+ final GenericBindRequest nextRequest =
+ bindClient.nextBindRequest();
+ ldapWriter.writeBindRequest(msgID, 3, nextRequest);
+ context.write(ldapWriter.getASN1Writer().getBuffer(), null);
+ } finally {
+ GrizzlyUtils.recycleWriter(ldapWriter);
}
-
- if (result.getResultCode() == ResultCode.SUCCESS) {
- final ConnectionSecurityLayer l =
- bindClient.getConnectionSecurityLayer();
- if (l != null) {
- // The connection needs to be secured by
- // the SASL mechanism.
- ldapConnection
- .installFilter(new ConnectionSecurityLayerFilter(l,
- ctx.getConnection().getTransport()
- .getMemoryManager()));
- }
- }
-
- ldapConnection.setBindOrStartTLSInProgress(false);
- future.setResultOrError(result);
return;
}
- throw new UnexpectedResponseException(messageID, result);
+ } catch (final ErrorResultException e) {
+ ldapConnection.setBindOrStartTLSInProgress(false);
+ future.adaptErrorResult(e.getResult());
+ return;
+ } catch (final IOException e) {
+ // FIXME: I18N need to have a better error
+ // message.
+ // FIXME: Is this the best result code?
+ ldapConnection.setBindOrStartTLSInProgress(false);
+ final Result errorResult =
+ Responses
+ .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
+ .setDiagnosticMessage(
+ "An error occurred during multi-stage authentication")
+ .setCause(e);
+ future.adaptErrorResult(errorResult);
+ return;
}
- }
- }
- @Override
- public void compareResult(final FilterChainContext ctx, final int messageID,
- final CompareResult result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPCompareFutureResultImpl) {
- final LDAPCompareFutureResultImpl future =
- (LDAPCompareFutureResultImpl) pendingRequest;
- future.setResultOrError(result);
- return;
+ if (result.getResultCode() == ResultCode.SUCCESS) {
+ final ConnectionSecurityLayer l =
+ bindClient.getConnectionSecurityLayer();
+ if (l != null) {
+ // The connection needs to be secured by
+ // the SASL mechanism.
+ ldapConnection
+ .installFilter(new ConnectionSecurityLayerFilter(l,
+ context.getConnection().getTransport()
+ .getMemoryManager()));
}
- throw new UnexpectedResponseException(messageID, result);
+ }
+
+ ldapConnection.setBindOrStartTLSInProgress(false);
+ future.setResultOrError(result);
+ return;
+ }
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+
+ @Override
+ public void compareResult(final int messageID, final CompareResult result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPCompareFutureResultImpl) {
+ final LDAPCompareFutureResultImpl future =
+ (LDAPCompareFutureResultImpl) pendingRequest;
+ future.setResultOrError(result);
+ return;
+ }
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+
+ @Override
+ public void deleteResult(final int messageID, final Result result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPFutureResultImpl) {
+ final LDAPFutureResultImpl future =
+ (LDAPFutureResultImpl) pendingRequest;
+ if (future.getRequest() instanceof DeleteRequest) {
+ future.setResultOrError(result);
+ return;
}
}
+ throw new UnexpectedResponseException(messageID, result);
}
+ }
+ }
- @Override
- public void deleteResult(final FilterChainContext ctx, final int messageID,
- final Result result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPFutureResultImpl) {
- final LDAPFutureResultImpl future =
- (LDAPFutureResultImpl) pendingRequest;
- if (future.getRequest() instanceof DeleteRequest) {
- future.setResultOrError(result);
- return;
- }
- }
- throw new UnexpectedResponseException(messageID, result);
- }
+ @Override
+ public void extendedResult(final int messageID, final ExtendedResult result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ if (messageID == 0) {
+ // Unsolicited notification received.
+ if ((result.getOID() != null)
+ && result.getOID().equals(OID_NOTICE_OF_DISCONNECTION)) {
+ // Treat this as a connection error.
+ final Result errorResult =
+ Responses
+ .newResult(result.getResultCode())
+ .setDiagnosticMessage(result.getDiagnosticMessage());
+ ldapConnection.close(null, true, errorResult);
+ } else {
+ ldapConnection.handleUnsolicitedNotification(result);
}
- }
+ } else {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
- @Override
- public void extendedResult(final FilterChainContext ctx, final int messageID,
- final ExtendedResult result) throws UnexpectedResponseException,
- IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- if (messageID == 0) {
- // Unsolicited notification received.
- if ((result.getOID() != null)
- && result.getOID().equals(OID_NOTICE_OF_DISCONNECTION)) {
- // Treat this as a connection error.
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPExtendedFutureResultImpl<?>) {
+ final LDAPExtendedFutureResultImpl<?> extendedFuture =
+ ((LDAPExtendedFutureResultImpl<?>) pendingRequest);
+ try {
+ handleExtendedResult0(ldapConnection, extendedFuture,
+ result);
+ } catch (final DecodeException de) {
+ // FIXME: should the connection be closed as
+ // well?
final Result errorResult =
- Responses
- .newResult(result.getResultCode())
- .setDiagnosticMessage(result.getDiagnosticMessage());
- ldapConnection.close(null, true, errorResult);
- } else {
- ldapConnection.handleUnsolicitedNotification(result);
+ Responses.newResult(
+ ResultCode.CLIENT_SIDE_DECODING_ERROR)
+ .setDiagnosticMessage(
+ de.getLocalizedMessage()).setCause(
+ de);
+ extendedFuture.adaptErrorResult(errorResult);
}
} else {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+ }
+ }
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPExtendedFutureResultImpl<?>) {
- final LDAPExtendedFutureResultImpl<?> extendedFuture =
- ((LDAPExtendedFutureResultImpl<?>) pendingRequest);
- try {
- handleExtendedResult0(ldapConnection, extendedFuture,
- result);
- } catch (final DecodeException de) {
- // FIXME: should the connection be closed as
- // well?
+ @Override
+ public void intermediateResponse(final int messageID, final IntermediateResponse response)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.getPendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ pendingRequest.handleIntermediateResponse(response);
+ }
+ }
+ }
+
+ @Override
+ public void modifyDNResult(final int messageID, final Result result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPFutureResultImpl) {
+ final LDAPFutureResultImpl future =
+ (LDAPFutureResultImpl) pendingRequest;
+ if (future.getRequest() instanceof ModifyDNRequest) {
+ future.setResultOrError(result);
+ return;
+ }
+ }
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+
+ @Override
+ public void modifyResult(final int messageID, final Result result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPFutureResultImpl) {
+ final LDAPFutureResultImpl future =
+ (LDAPFutureResultImpl) pendingRequest;
+ if (future.getRequest() instanceof ModifyRequest) {
+ future.setResultOrError(result);
+ return;
+ }
+ }
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+
+ @Override
+ public void searchResult(final int messageID, final Result result)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.removePendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
+ ((LDAPSearchFutureResultImpl) pendingRequest)
+ .setResultOrError(result);
+ } else {
+ throw new UnexpectedResponseException(messageID, result);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void searchResultEntry(final int messageID, final SearchResultEntry entry)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.getPendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
+ ((LDAPSearchFutureResultImpl) pendingRequest).handleEntry(entry);
+ } else {
+ throw new UnexpectedResponseException(messageID, entry);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void searchResultReference(final int messageID, final SearchResultReference reference)
+ throws UnexpectedResponseException, IOException {
+ final GrizzlyLDAPConnection ldapConnection =
+ LDAP_CONNECTION_ATTR.get(context.getConnection());
+ if (ldapConnection != null) {
+ final AbstractLDAPFutureResultImpl<?> pendingRequest =
+ ldapConnection.getPendingRequest(messageID);
+
+ if (pendingRequest != null) {
+ if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
+ ((LDAPSearchFutureResultImpl) pendingRequest)
+ .handleReference(reference);
+ } else {
+ throw new UnexpectedResponseException(messageID, reference);
+ }
+ }
+ }
+ }
+
+ // Needed in order to expose type information.
+ private <R extends ExtendedResult> void handleExtendedResult0(
+ final GrizzlyLDAPConnection conn, final LDAPExtendedFutureResultImpl<R> future,
+ final ExtendedResult result) throws DecodeException {
+ final R decodedResponse =
+ future.decodeResult(result, conn.getLDAPOptions().getDecodeOptions());
+
+ if (future.getRequest() instanceof StartTLSExtendedRequest) {
+ if (result.getResultCode() == ResultCode.SUCCESS) {
+ try {
+ final StartTLSExtendedRequest request =
+ (StartTLSExtendedRequest) future.getRequest();
+ conn.startTLS(request.getSSLContext(), request
+ .getEnabledProtocols(), request.getEnabledCipherSuites(),
+ new EmptyCompletionHandler<SSLEngine>() {
+ @Override
+ public void completed(final SSLEngine result) {
+ conn.setBindOrStartTLSInProgress(false);
+ future.setResultOrError(decodedResponse);
+ }
+
+ @Override
+ public void failed(final Throwable throwable) {
final Result errorResult =
Responses.newResult(
- ResultCode.CLIENT_SIDE_DECODING_ERROR)
+ ResultCode.CLIENT_SIDE_LOCAL_ERROR)
+ .setCause(throwable)
.setDiagnosticMessage(
- de.getLocalizedMessage()).setCause(
- de);
- extendedFuture.adaptErrorResult(errorResult);
+ "SSL handshake failed");
+ conn.setBindOrStartTLSInProgress(false);
+ conn.close(null, false, errorResult);
+ future.adaptErrorResult(errorResult);
}
- } else {
- throw new UnexpectedResponseException(messageID, result);
- }
- }
- }
+ });
+ return;
+ } catch (final IOException e) {
+ final Result errorResult =
+ Responses.newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
+ .setCause(e).setDiagnosticMessage(e.getMessage());
+ future.adaptErrorResult(errorResult);
+ conn.close(null, false, errorResult);
+ return;
}
}
+ }
- @Override
- public void intermediateResponse(final FilterChainContext ctx, final int messageID,
- final IntermediateResponse response) throws UnexpectedResponseException,
- IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.getPendingRequest(messageID);
+ future.setResultOrError(decodedResponse);
+ }
+ }
- if (pendingRequest != null) {
- pendingRequest.handleIntermediateResponse(response);
- }
- }
- }
-
- @Override
- public void modifyDNResult(final FilterChainContext ctx, final int messageID,
- final Result result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPFutureResultImpl) {
- final LDAPFutureResultImpl future =
- (LDAPFutureResultImpl) pendingRequest;
- if (future.getRequest() instanceof ModifyDNRequest) {
- future.setResultOrError(result);
- return;
- }
- }
- throw new UnexpectedResponseException(messageID, result);
- }
- }
- }
-
- @Override
- public void modifyResult(final FilterChainContext ctx, final int messageID,
- final Result result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPFutureResultImpl) {
- final LDAPFutureResultImpl future =
- (LDAPFutureResultImpl) pendingRequest;
- if (future.getRequest() instanceof ModifyRequest) {
- future.setResultOrError(result);
- return;
- }
- }
- throw new UnexpectedResponseException(messageID, result);
- }
- }
- }
-
- @Override
- public void searchResult(final FilterChainContext ctx, final int messageID,
- final Result result) throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.removePendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
- ((LDAPSearchFutureResultImpl) pendingRequest)
- .setResultOrError(result);
- } else {
- throw new UnexpectedResponseException(messageID, result);
- }
- }
- }
- }
-
- @Override
- public void searchResultEntry(final FilterChainContext ctx, final int messageID,
- final SearchResultEntry entry) throws UnexpectedResponseException,
- IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.getPendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
- ((LDAPSearchFutureResultImpl) pendingRequest).handleEntry(entry);
- } else {
- throw new UnexpectedResponseException(messageID, entry);
- }
- }
- }
- }
-
- @Override
- public void searchResultReference(final FilterChainContext ctx,
- final int messageID, final SearchResultReference reference)
- throws UnexpectedResponseException, IOException {
- final GrizzlyLDAPConnection ldapConnection =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (ldapConnection != null) {
- final AbstractLDAPFutureResultImpl<?> pendingRequest =
- ldapConnection.getPendingRequest(messageID);
-
- if (pendingRequest != null) {
- if (pendingRequest instanceof LDAPSearchFutureResultImpl) {
- ((LDAPSearchFutureResultImpl) pendingRequest)
- .handleReference(reference);
- } else {
- throw new UnexpectedResponseException(messageID, reference);
- }
- }
- }
- }
-
- // Needed in order to expose type information.
- private <R extends ExtendedResult> void handleExtendedResult0(
- final GrizzlyLDAPConnection conn, final LDAPExtendedFutureResultImpl<R> future,
- final ExtendedResult result) throws DecodeException {
- final R decodedResponse =
- future.decodeResult(result, conn.getLDAPOptions().getDecodeOptions());
-
- if (future.getRequest() instanceof StartTLSExtendedRequest) {
- if (result.getResultCode() == ResultCode.SUCCESS) {
- try {
- final StartTLSExtendedRequest request =
- (StartTLSExtendedRequest) future.getRequest();
- conn.startTLS(request.getSSLContext(), request
- .getEnabledProtocols(), request.getEnabledCipherSuites(),
- new EmptyCompletionHandler<SSLEngine>() {
- @Override
- public void completed(final SSLEngine result) {
- conn.setBindOrStartTLSInProgress(false);
- future.setResultOrError(decodedResponse);
- }
-
- @Override
- public void failed(final Throwable throwable) {
- final Result errorResult =
- Responses.newResult(
- ResultCode.CLIENT_SIDE_LOCAL_ERROR)
- .setCause(throwable)
- .setDiagnosticMessage(
- "SSL handshake failed");
- conn.setBindOrStartTLSInProgress(false);
- conn.close(null, false, errorResult);
- future.adaptErrorResult(errorResult);
- }
- });
- return;
- } catch (final IOException e) {
- final Result errorResult =
- Responses.newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR)
- .setCause(e).setDiagnosticMessage(e.getMessage());
- future.adaptErrorResult(errorResult);
- conn.close(null, false, errorResult);
- return;
- }
- }
- }
-
- future.setResultOrError(decodedResponse);
- }
- };
-
- LDAPClientFilter(final LDAPReader ldapReader, final int maxASN1ElementSize) {
- this.ldapReader = ldapReader;
+ /**
+ * Creates a client filter with provided options and max size of ASN1
+ * elements.
+ *
+ * @param options
+ * allow to control how request and responses are decoded
+ * @param maxASN1ElementSize
+ * The maximum BER element size, or <code>0</code> to indicate
+ * that there is no limit.
+ */
+ LDAPClientFilter(final DecodeOptions options, final int maxASN1ElementSize) {
+ this.decodeOptions = options;
this.maxASN1ElementSize = maxASN1ElementSize;
}
@@ -490,27 +526,23 @@
@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();
- ASN1BufferReader asn1Reader = LDAP_ASN1_READER_ATTR.get(ctx.getConnection());
- if (asn1Reader == null) {
- asn1Reader =
- new ASN1BufferReader(maxASN1ElementSize, ctx.getConnection().getTransport()
- .getMemoryManager());
- LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader);
- }
- asn1Reader.appendBytesRead(buffer);
+ asn1Reader.appendBytesRead(buffer);
try {
- while (asn1Reader.elementAvailable()) {
- ldapReader.decode(asn1Reader, CLIENT_RESPONSE_HANDLER, ctx);
+ while (reader.hasMessageAvailable()) {
+ reader.readMessage(handler);
}
- } catch (IOException ioe) {
+ } catch (IOException e) {
final GrizzlyLDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx.getConnection());
final Result errorResult =
- Responses.newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR).setCause(ioe)
- .setDiagnosticMessage(ioe.getMessage());
+ Responses.newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR).setCause(e)
+ .setDiagnosticMessage(e.getMessage());
ldapConnection.close(null, false, errorResult);
- throw ioe;
+ throw e;
} finally {
asn1Reader.disposeBytesRead();
}
@@ -518,6 +550,39 @@
return ctx.getStopAction();
}
+ /**
+ * Returns the response handler associated to the provided connection and
+ * context.
+ * <p>
+ * If no handler exists yet for this context, a new one is created and
+ * recorded for the connection.
+ *
+ * @param ctx
+ * current filter chain context
+ * @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) {
+ Connection<?> connection = ctx.getConnection();
+ ClientResponseHandler handler = RESPONSE_HANDLER_ATTR.get(connection);
+ if (handler == null) {
+ LDAPReader<ASN1BufferReader> reader = GrizzlyUtils.createReader(decodeOptions,
+ maxASN1ElementSize, connection.getTransport().getMemoryManager());
+ handler = new ClientResponseHandler(reader);
+ RESPONSE_HANDLER_ATTR.set(connection, handler);
+ }
+ handler.setFilterChainContext(ctx);
+ return handler;
+ }
+
+ /**
+ * Associate a LDAP connection to the provided Grizzly connection.
+ *
+ * @param connection
+ * Grizzly connection
+ * @param ldapConnection
+ * LDAP connection
+ */
void registerConnection(final Connection<?> connection, final GrizzlyLDAPConnection ldapConnection) {
LDAP_CONNECTION_ATTR.set(connection, ldapConnection);
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPMessageHandler.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPMessageHandler.java
deleted file mode 100644
index 7104540..0000000
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPMessageHandler.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 2009 Sun Microsystems, Inc.
- */
-
-package com.forgerock.opendj.grizzly;
-
-import java.io.IOException;
-
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.requests.AbandonRequest;
-import org.forgerock.opendj.ldap.requests.AddRequest;
-import org.forgerock.opendj.ldap.requests.CompareRequest;
-import org.forgerock.opendj.ldap.requests.DeleteRequest;
-import org.forgerock.opendj.ldap.requests.ExtendedRequest;
-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.SearchRequest;
-import org.forgerock.opendj.ldap.requests.UnbindRequest;
-import org.forgerock.opendj.ldap.responses.BindResult;
-import org.forgerock.opendj.ldap.responses.CompareResult;
-import org.forgerock.opendj.ldap.responses.ExtendedResult;
-import org.forgerock.opendj.ldap.responses.IntermediateResponse;
-import org.forgerock.opendj.ldap.responses.Result;
-import org.forgerock.opendj.ldap.responses.SearchResultEntry;
-import org.forgerock.opendj.ldap.responses.SearchResultReference;
-
-/**
- * LDAP message handler interface.
- *
- * @param <P>
- * A user provided handler parameter.
- */
-interface LDAPMessageHandler<P> {
- void abandonRequest(P param, int messageID, AbandonRequest request)
- throws UnexpectedRequestException, IOException;
-
- void addRequest(P param, int messageID, AddRequest request) throws UnexpectedRequestException,
- IOException;
-
- void addResult(P param, int messageID, Result result) throws UnexpectedResponseException,
- IOException;
-
- void bindRequest(P param, int messageID, int version, GenericBindRequest request)
- throws UnexpectedRequestException, IOException;
-
- void bindResult(P param, int messageID, BindResult result) throws UnexpectedResponseException,
- IOException;
-
- void compareRequest(P param, int messageID, CompareRequest request)
- throws UnexpectedRequestException, IOException;
-
- void compareResult(P param, int messageID, CompareResult result)
- throws UnexpectedResponseException, IOException;
-
- void deleteRequest(P param, int messageID, DeleteRequest request)
- throws UnexpectedRequestException, IOException;
-
- void deleteResult(P param, int messageID, Result result) throws UnexpectedResponseException,
- IOException;
-
- <R extends ExtendedResult> void extendedRequest(P param, int messageID,
- ExtendedRequest<R> request) throws UnexpectedRequestException, IOException;
-
- void extendedResult(P param, int messageID, ExtendedResult result)
- throws UnexpectedResponseException, IOException;
-
- void intermediateResponse(P param, int messageID, IntermediateResponse response)
- throws UnexpectedResponseException, IOException;
-
- void modifyDNRequest(P param, int messageID, ModifyDNRequest request)
- throws UnexpectedRequestException, IOException;
-
- void modifyDNResult(P param, int messageID, Result result) throws UnexpectedResponseException,
- IOException;
-
- void modifyRequest(P param, int messageID, ModifyRequest request)
- throws UnexpectedRequestException, IOException;
-
- void modifyResult(P param, int messageID, Result result) throws UnexpectedResponseException,
- IOException;
-
- void searchRequest(P param, int messageID, SearchRequest request)
- throws UnexpectedRequestException, IOException;
-
- void searchResult(P param, int messageID, Result result) throws UnexpectedResponseException,
- IOException;
-
- void searchResultEntry(P param, int messageID, SearchResultEntry entry)
- throws UnexpectedResponseException, IOException;
-
- void searchResultReference(P param, int messageID, SearchResultReference reference)
- throws UnexpectedResponseException, IOException;
-
- void unbindRequest(P param, int messageID, UnbindRequest request)
- throws UnexpectedRequestException, IOException;
-
- void unrecognizedMessage(P param, int messageID, byte messageTag, ByteString messageBytes)
- throws UnsupportedMessageException, IOException;
-}
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 f0c9f43..33c5d61 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
@@ -38,8 +38,11 @@
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
+import org.forgerock.opendj.io.LDAPReader;
+import org.forgerock.opendj.io.LDAPWriter;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConnectionSecurityLayer;
+import org.forgerock.opendj.ldap.DecodeOptions;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.LDAPClientContext;
@@ -69,6 +72,9 @@
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.responses.SearchResultReference;
+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;
@@ -89,33 +95,113 @@
* side logic for SSL and SASL operations over LDAP.
*/
final class LDAPServerFilter extends BaseFilter {
- private abstract class AbstractHandler<R extends Result> implements
+
+ /**
+ * Provides an arbitrary write operation on a LDAP writer.
+ */
+ private interface LDAPWrite<T> {
+ void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, T message) throws IOException;
+ }
+
+ /**
+ * Write operation for intermediate responses.
+ */
+ private static final LDAPWrite<IntermediateResponse> INTERMEDIATE = new LDAPWrite<IntermediateResponse>() {
+ public void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, IntermediateResponse resp)
+ throws IOException {
+ writer.writeIntermediateResponse(messageID, resp);
+ }
+ };
+
+ private static abstract class AbstractHandler<R extends Result> implements
IntermediateResponseHandler, ResultHandler<R> {
protected final ClientContextImpl context;
protected final int messageID;
+
protected AbstractHandler(final ClientContextImpl context, final int messageID) {
this.messageID = messageID;
this.context = context;
}
@Override
+ public void handleResult(final R result) {
+ defaultHandleResult(result);
+ }
+
+ @Override
public final boolean handleIntermediateResponse(final IntermediateResponse response) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ writeMessage(INTERMEDIATE, response);
+ return true;
+ }
+
+ /**
+ * Default implementation of result handling, that delegate
+ * the actual write operation to {@code writeResult} method.
+ */
+ private void defaultHandleResult(final R result) {
+ writeMessage(new LDAPWrite<R>() {
+ public void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, R res) throws IOException {
+ writeResult(writer, res);
+ }
+ }, result);
+ }
+
+ /**
+ * Write a result to provided LDAP writer.
+ *
+ * @param ldapWriter
+ * provided writer
+ * @param result
+ * to write
+ * @throws IOException
+ * if an error occurs during writing
+ */
+ abstract protected void writeResult(final LDAPWriter<ASN1BufferWriter> ldapWriter, final R result)
+ throws IOException;
+
+ /**
+ * Write a message on LDAP writer.
+ *
+ * @param <T>
+ * type of message to write
+ * @param ldapWrite
+ * the specific write operation
+ * @param message
+ * the message to write
+ */
+ protected final <T> void writeMessage(final LDAPWrite<T> ldapWrite, final T message) {
+ final LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- LDAP_WRITER.intermediateResponse(asn1Writer, messageID, response);
- context.write(asn1Writer);
+ ldapWrite.perform(writer, messageID, message);
+ context.write(writer);
} catch (final IOException ioe) {
context.handleError(ioe);
- return false;
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
- return true;
+ }
+
+ /**
+ * Copy diagnostic message, matched DN and cause to new result from the
+ * given result.
+ *
+ * @param newResult
+ * to update
+ * @param result
+ * contains parameters to copy
+ */
+ protected final void populateNewResultFromResult(final R newResult, final Result result) {
+ newResult.setDiagnosticMessage(result.getDiagnosticMessage());
+ newResult.setMatchedDN(result.getMatchedDN());
+ newResult.setCause(result.getCause());
+ for (final Control control : result.getControls()) {
+ newResult.addControl(control);
+ }
}
}
- private final class AddHandler extends AbstractHandler<Result> {
+ private static final class AddHandler extends AbstractHandler<Result> {
private AddHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -126,20 +212,13 @@
}
@Override
- public void handleResult(final Result result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.addResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ public void writeResult(LDAPWriter<ASN1BufferWriter> writer, final Result result)
+ throws IOException {
+ writer.writeAddResult(messageID, result);
}
}
- private final class BindHandler extends AbstractHandler<BindResult> {
+ private static final class BindHandler extends AbstractHandler<BindResult> {
private BindHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -151,31 +230,19 @@
handleResult((BindResult) result);
} else {
final BindResult newResult = Responses.newBindResult(result.getResultCode());
- newResult.setDiagnosticMessage(result.getDiagnosticMessage());
- newResult.setMatchedDN(result.getMatchedDN());
- newResult.setCause(result.getCause());
- for (final Control control : result.getControls()) {
- newResult.addControl(control);
- }
+ populateNewResultFromResult(newResult, result);
handleResult(newResult);
}
}
@Override
- public void handleResult(final BindResult result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.bindResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, BindResult result)
+ throws IOException {
+ writer.writeBindResult(messageID, result);
}
}
- private final class ClientContextImpl implements LDAPClientContext {
+ private static final class ClientContextImpl implements LDAPClientContext {
private final Connection<?> connection;
private final AtomicBoolean isClosed = new AtomicBoolean();
private ServerConnection<Integer> serverConnection = null;
@@ -263,14 +330,14 @@
@Override
public void sendUnsolicitedNotification(final ExtendedResult notification) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+ LDAPWriter<ASN1BufferWriter> writer = GrizzlyUtils.getWriter();
try {
- LDAP_WRITER.extendedResult(asn1Writer, 0, notification);
- connection.write(asn1Writer.getBuffer(), null);
+ writer.writeExtendedResult(0, notification);
+ connection.write(writer.getASN1Writer().getBuffer(), null);
} catch (final IOException ioe) {
handleError(ioe);
} finally {
- asn1Writer.recycle();
+ GrizzlyUtils.recycleWriter(writer);
}
}
@@ -288,8 +355,8 @@
return builder.toString();
}
- public void write(final ASN1BufferWriter asn1Writer) {
- connection.write(asn1Writer.getBuffer(), null);
+ public void write(final LDAPWriter<ASN1BufferWriter> writer) {
+ connection.write(writer.getASN1Writer().getBuffer(), null);
}
private void disconnect0(final ResultCode resultCode, final String message) {
@@ -385,7 +452,7 @@
}
}
- private final class CompareHandler extends AbstractHandler<CompareResult> {
+ private static final class CompareHandler extends AbstractHandler<CompareResult> {
private CompareHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -397,31 +464,20 @@
handleResult((CompareResult) result);
} else {
final CompareResult newResult = Responses.newCompareResult(result.getResultCode());
- newResult.setDiagnosticMessage(result.getDiagnosticMessage());
- newResult.setMatchedDN(result.getMatchedDN());
- newResult.setCause(result.getCause());
- for (final Control control : result.getControls()) {
- newResult.addControl(control);
- }
+ populateNewResultFromResult(newResult, result);
handleResult(newResult);
}
}
@Override
- public void handleResult(final CompareResult result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.compareResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, CompareResult result)
+ throws IOException {
+ writer.writeCompareResult(messageID, result);
+
}
}
- private final class DeleteHandler extends AbstractHandler<Result> {
+ private static final class DeleteHandler extends AbstractHandler<Result> {
private DeleteHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -432,20 +488,13 @@
}
@Override
- public void handleResult(final Result result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.deleteResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, Result result)
+ throws IOException {
+ writer.writeDeleteResult(messageID, result);
}
}
- private final class ExtendedHandler<R extends ExtendedResult> extends AbstractHandler<R> {
+ private static final class ExtendedHandler<R extends ExtendedResult> extends AbstractHandler<R> {
private ExtendedHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -470,19 +519,21 @@
@Override
public void handleResult(final ExtendedResult result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.extendedResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ writeMessage(new LDAPWrite<ExtendedResult>() {
+ public void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, ExtendedResult message)
+ throws IOException {
+ writer.writeExtendedResult(messageID, message);
+ }
+ }, result);
+ }
+
+ @Override
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> ldapWriter, R result) throws IOException {
+ // never called because handleResult(result) method is overriden in this class
}
}
- private final class ModifyDNHandler extends AbstractHandler<Result> {
+ private static final class ModifyDNHandler extends AbstractHandler<Result> {
private ModifyDNHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -493,20 +544,13 @@
}
@Override
- public void handleResult(final Result result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.modifyDNResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, Result result)
+ throws IOException {
+ writer.writeModifyDNResult(messageID, result);
}
}
- private final class ModifyHandler extends AbstractHandler<Result> {
+ private static final class ModifyHandler extends AbstractHandler<Result> {
private ModifyHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
}
@@ -517,20 +561,13 @@
}
@Override
- public void handleResult(final Result result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.modifyResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, Result result)
+ throws IOException {
+ writer.writeModifyResult(messageID, result);
}
}
- private final class SearchHandler extends AbstractHandler<Result> implements
+ private static final class SearchHandler extends AbstractHandler<Result> implements
SearchResultHandler {
private SearchHandler(final ClientContextImpl context, final int messageID) {
super(context, messageID);
@@ -538,16 +575,12 @@
@Override
public boolean handleEntry(final SearchResultEntry entry) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.searchResultEntry(asn1Writer, messageID, entry);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- return false;
- } finally {
- asn1Writer.recycle();
- }
+ writeMessage(new LDAPWrite<SearchResultEntry>() {
+ public void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, SearchResultEntry sre)
+ throws IOException {
+ writer.writeSearchResultEntry(messageID, sre);
+ }
+ }, entry);
return true;
}
@@ -558,30 +591,19 @@
@Override
public boolean handleReference(final SearchResultReference reference) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.searchResultReference(asn1Writer, messageID, reference);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- return false;
- } finally {
- asn1Writer.recycle();
- }
+ writeMessage(new LDAPWrite<SearchResultReference>() {
+ public void perform(LDAPWriter<ASN1BufferWriter> writer, int messageID, SearchResultReference ref)
+ throws IOException {
+ writer.writeSearchResultReference(messageID, ref);
+ }
+ }, reference);
return true;
}
@Override
- public void handleResult(final Result result) {
- final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
- try {
- LDAP_WRITER.searchResult(asn1Writer, messageID, result);
- context.write(asn1Writer);
- } catch (final IOException ioe) {
- context.handleError(ioe);
- } finally {
- asn1Writer.recycle();
- }
+ protected void writeResult(LDAPWriter<ASN1BufferWriter> writer, Result result)
+ throws IOException {
+ writer.writeSearchResult(messageID, result);
}
}
@@ -613,13 +635,11 @@
// Default maximum request size for incoming requests.
private static final int DEFAULT_MAX_REQUEST_SIZE = 5 * 1024 * 1024;
- private static final Attribute<ASN1BufferReader> LDAP_ASN1_READER_ATTR =
- Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPASN1Reader");
-
private static final Attribute<ClientContextImpl> LDAP_CONNECTION_ATTR =
Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPServerConnection");
- private static final LDAPWriter LDAP_WRITER = new LDAPWriter();
+ private static final Attribute<ServerRequestHandler> REQUEST_HANDLER_ATTR =
+ Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("ServerRequestHandler");
/**
* A dummy SSL client engine configurator as SSLFilter only needs server
@@ -638,154 +658,191 @@
}
}
- private final LDAPReader ldapReader;
private final GrizzlyLDAPListener listener;
private final int maxASN1ElementSize;
+ private final DecodeOptions decodeOptions;
- private final AbstractLDAPMessageHandler<FilterChainContext> serverRequestHandler =
- new AbstractLDAPMessageHandler<FilterChainContext>() {
- @Override
- public void abandonRequest(final FilterChainContext ctx, final int messageID,
- final AbandonRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- conn.handleAbandon(messageID, request);
- }
- }
+ private static final class ServerRequestHandler extends AbstractLDAPMessageHandler {
- @Override
- public void addRequest(final FilterChainContext ctx, final int messageID,
- final AddRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final AddHandler handler = new AddHandler(clientContext, messageID);
- conn.handleAdd(messageID, request, handler, handler);
- }
- }
+ private final Connection<?> connection;
+ private final LDAPReader<ASN1BufferReader> reader;
- @Override
- public void bindRequest(final FilterChainContext ctx, final int messageID,
- final int version, final GenericBindRequest request)
- throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final BindHandler handler = new BindHandler(clientContext, messageID);
- conn.handleBind(messageID, version, request, handler, handler);
- }
- }
+ /**
+ * Creates the handler with a connection.
+ *
+ * @param connection
+ * connection this handler is associated with
+ * @param reader
+ * LDAP reader to use for reading incoming messages
+ */
+ ServerRequestHandler(Connection<?> connection, LDAPReader<ASN1BufferReader> reader) {
+ this.connection = connection;
+ this.reader = reader;
+ }
- @Override
- public void compareRequest(final FilterChainContext ctx, final int messageID,
- final CompareRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final CompareHandler handler = new CompareHandler(clientContext, messageID);
- conn.handleCompare(messageID, request, handler, handler);
- }
- }
+ /**
+ * Returns the LDAP reader.
+ *
+ * @return the reader to read incoming LDAP messages
+ */
+ public LDAPReader<ASN1BufferReader> getReader() {
+ return reader;
+ }
- @Override
- public void deleteRequest(final FilterChainContext ctx, final int messageID,
- final DeleteRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final DeleteHandler handler = new DeleteHandler(clientContext, messageID);
- conn.handleDelete(messageID, request, handler, handler);
- }
- }
+ @Override
+ public void abandonRequest(final int messageID, final AbandonRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ conn.handleAbandon(messageID, request);
+ }
+ }
- @Override
- public <R extends ExtendedResult> void extendedRequest(
- final FilterChainContext ctx, final int messageID,
- final ExtendedRequest<R> request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final ExtendedHandler<R> handler =
- new ExtendedHandler<R>(clientContext, messageID);
- conn.handleExtendedRequest(messageID, request, handler, handler);
- }
- }
+ @Override
+ public void addRequest(final int messageID, final AddRequest request) throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final AddHandler handler = new AddHandler(clientContext, messageID);
+ conn.handleAdd(messageID, request, handler, handler);
+ }
+ }
- @Override
- public void modifyDNRequest(final FilterChainContext ctx, final int messageID,
- final ModifyDNRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final ModifyDNHandler handler =
- new ModifyDNHandler(clientContext, messageID);
- conn.handleModifyDN(messageID, request, handler, handler);
- }
- }
+ @Override
+ public void bindRequest(final int messageID, final int version,
+ final GenericBindRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final AbstractHandler<BindResult> handler = new BindHandler(clientContext, messageID);
+ conn.handleBind(messageID, version, request, handler, handler);
+ }
+ }
- @Override
- public void modifyRequest(final FilterChainContext ctx, final int messageID,
- final ModifyRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final ModifyHandler handler = new ModifyHandler(clientContext, messageID);
- conn.handleModify(messageID, request, handler, handler);
- }
- }
+ @Override
+ public void compareRequest(final int messageID, final CompareRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final CompareHandler handler = new CompareHandler(clientContext, messageID);
+ conn.handleCompare(messageID, request, handler, handler);
+ }
+ }
- @Override
- public void searchRequest(final FilterChainContext ctx, final int messageID,
- final SearchRequest request) throws UnexpectedRequestException {
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.get(ctx.getConnection());
- if (clientContext != null) {
- final ServerConnection<Integer> conn = clientContext.getServerConnection();
- final SearchHandler handler = new SearchHandler(clientContext, messageID);
- conn.handleSearch(messageID, request, handler, handler);
- }
- }
+ @Override
+ public void deleteRequest(final int messageID, final DeleteRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final DeleteHandler handler = new DeleteHandler(clientContext, messageID);
+ conn.handleDelete(messageID, request, handler, handler);
+ }
+ }
- @Override
- public void unbindRequest(final FilterChainContext ctx, final int messageID,
- final UnbindRequest request) {
- // Remove the client context causing any subsequent LDAP
- // traffic to be ignored.
- final ClientContextImpl clientContext =
- LDAP_CONNECTION_ATTR.remove(ctx.getConnection());
- if (clientContext != null) {
- clientContext.handleClose(messageID, request);
- }
- }
+ @Override
+ public <R extends ExtendedResult> void extendedRequest(
+ final int messageID,
+ final ExtendedRequest<R> request) throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final ExtendedHandler<R> handler = new ExtendedHandler<R>(clientContext, messageID);
+ conn.handleExtendedRequest(messageID, request, handler, handler);
+ }
+ }
- @Override
- public void unrecognizedMessage(final FilterChainContext ctx, final int messageID,
- final byte messageTag, final ByteString messageBytes) {
- exceptionOccurred(ctx, new UnsupportedMessageException(messageID, messageTag,
- messageBytes));
- }
- };
+ @Override
+ public void modifyDNRequest(final int messageID, final ModifyDNRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final ModifyDNHandler handler = new ModifyDNHandler(clientContext, messageID);
+ conn.handleModifyDN(messageID, request, handler, handler);
+ }
+ }
- LDAPServerFilter(final GrizzlyLDAPListener listener, final LDAPReader ldapReader,
+ @Override
+ public void modifyRequest(final int messageID, final ModifyRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final ModifyHandler handler = new ModifyHandler(clientContext, messageID);
+ conn.handleModify(messageID, request, handler, handler);
+ }
+ }
+
+ @Override
+ public void searchRequest(final int messageID, final SearchRequest request)
+ throws UnexpectedRequestException {
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.get(connection);
+ if (clientContext != null) {
+ final ServerConnection<Integer> conn = clientContext.getServerConnection();
+ final SearchHandler handler = new SearchHandler(clientContext, messageID);
+ conn.handleSearch(messageID, request, handler, handler);
+ }
+ }
+
+ @Override
+ public void unbindRequest(final int messageID, final UnbindRequest request) {
+ // Remove the client context causing any subsequent LDAP
+ // traffic to be ignored.
+ final ClientContextImpl clientContext =
+ LDAP_CONNECTION_ATTR.remove(connection);
+ if (clientContext != null) {
+ clientContext.handleClose(messageID, request);
+ }
+ }
+
+ @Override
+ public void unrecognizedMessage(final int messageID, final byte messageTag,
+ final ByteString messageBytes) {
+ exceptionOccurred(connection, new UnsupportedMessageException(messageID, messageTag,
+ messageBytes));
+ }
+ }
+
+ /**
+ * Creates a server filter with provided listener, options and max size of
+ * ASN1 element.
+ *
+ * @param listener
+ * listen for incoming connections
+ * @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.
+ */
+ LDAPServerFilter(final GrizzlyLDAPListener listener, final DecodeOptions options,
final int maxASN1ElementSize) {
this.listener = listener;
- this.ldapReader = ldapReader;
+ this.decodeOptions = options;
this.maxASN1ElementSize =
maxASN1ElementSize <= 0 ? DEFAULT_MAX_REQUEST_SIZE : maxASN1ElementSize;
}
@Override
public void exceptionOccurred(final FilterChainContext ctx, final Throwable error) {
- final ClientContextImpl clientContext = LDAP_CONNECTION_ATTR.remove(ctx.getConnection());
+ exceptionOccurred(ctx.getConnection(), error);
+ }
+
+ private static void exceptionOccurred(final Connection<?> connection, final Throwable error) {
+ final ClientContextImpl clientContext = LDAP_CONNECTION_ATTR.remove(connection);
if (clientContext != null) {
clientContext.handleError(error);
}
@@ -819,19 +876,15 @@
@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();
- ASN1BufferReader asn1Reader = LDAP_ASN1_READER_ATTR.get(ctx.getConnection());
- if (asn1Reader == null) {
- asn1Reader =
- new ASN1BufferReader(maxASN1ElementSize, ctx.getConnection().getTransport()
- .getMemoryManager());
- LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader);
- }
- asn1Reader.appendBytesRead(buffer);
+ asn1Reader.appendBytesRead(buffer);
try {
- while (asn1Reader.elementAvailable()) {
- ldapReader.decode(asn1Reader, serverRequestHandler, ctx);
+ while (reader.hasMessageAvailable()) {
+ reader.readMessage(requestHandler);
}
} catch (IOException e) {
exceptionOccurred(ctx, e);
@@ -842,4 +895,26 @@
return ctx.getStopAction();
}
+
+ /**
+ * Returns the request handler associated to a connection.
+ * <p>
+ * If no handler exists yet for this context, a new one is created and
+ * recorded for the context.
+ *
+ * @param ctx
+ * Context
+ * @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) {
+ ServerRequestHandler handler = REQUEST_HANDLER_ATTR.get(connection);
+ if (handler == null) {
+ LDAPReader<ASN1BufferReader> reader = GrizzlyUtils.createReader(decodeOptions,
+ maxASN1ElementSize, connection.getTransport().getMemoryManager());
+ handler = new ServerRequestHandler(connection, reader);
+ REQUEST_HANDLER_ATTR.set(connection, handler);
+ }
+ return handler;
+ }
}
diff --git a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPWriter.java b/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPWriter.java
deleted file mode 100644
index b3e2fa9..0000000
--- a/opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPWriter.java
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * 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 2009-2010 Sun Microsystems, Inc.
- * Portions copyright 2011-2013 ForgeRock AS
- */
-
-package com.forgerock.opendj.grizzly;
-
-import static com.forgerock.opendj.ldap.LDAPConstants.*;
-import static com.forgerock.opendj.util.StaticUtils.IO_LOG;
-import static com.forgerock.opendj.util.StaticUtils.byteToHex;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.forgerock.opendj.asn1.ASN1Writer;
-import org.forgerock.opendj.ldap.Attribute;
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.DN;
-import org.forgerock.opendj.ldap.Modification;
-import org.forgerock.opendj.ldap.controls.Control;
-import org.forgerock.opendj.ldap.requests.AbandonRequest;
-import org.forgerock.opendj.ldap.requests.AddRequest;
-import org.forgerock.opendj.ldap.requests.CompareRequest;
-import org.forgerock.opendj.ldap.requests.DeleteRequest;
-import org.forgerock.opendj.ldap.requests.ExtendedRequest;
-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.Request;
-import org.forgerock.opendj.ldap.requests.SearchRequest;
-import org.forgerock.opendj.ldap.requests.UnbindRequest;
-import org.forgerock.opendj.ldap.responses.BindResult;
-import org.forgerock.opendj.ldap.responses.CompareResult;
-import org.forgerock.opendj.ldap.responses.ExtendedResult;
-import org.forgerock.opendj.ldap.responses.IntermediateResponse;
-import org.forgerock.opendj.ldap.responses.Response;
-import org.forgerock.opendj.ldap.responses.Result;
-import org.forgerock.opendj.ldap.responses.SearchResultEntry;
-import org.forgerock.opendj.ldap.responses.SearchResultReference;
-
-import com.forgerock.opendj.ldap.LDAPUtils;
-import com.forgerock.opendj.util.StaticUtils;
-
-/**
- * Static methods for encoding LDAP messages.
- */
-final class LDAPWriter implements LDAPMessageHandler<ASN1Writer> {
- public static void encodeControl(final ASN1Writer writer, final Control control)
- throws IOException {
- writer.writeStartSequence();
- writer.writeOctetString(control.getOID());
- if (control.isCritical()) {
- writer.writeBoolean(control.isCritical());
- }
- if (control.getValue() != null) {
- writer.writeOctetString(control.getValue());
- }
- writer.writeEndSequence();
- }
-
- public static void encodeEntry(final ASN1Writer writer,
- final SearchResultEntry searchResultEntry) throws IOException {
- writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
- writer.writeOctetString(searchResultEntry.getName().toString());
-
- writer.writeStartSequence();
- for (final Attribute attr : searchResultEntry.getAllAttributes()) {
- encodeAttribute(writer, attr);
- }
- writer.writeEndSequence();
- writer.writeEndSequence();
- }
-
- private static void encodeAttribute(final ASN1Writer writer, final Attribute attribute)
- throws IOException {
- writer.writeStartSequence();
- writer.writeOctetString(attribute.getAttributeDescriptionAsString());
-
- writer.writeStartSet();
- for (final ByteString value : attribute) {
- writer.writeOctetString(value);
- }
- writer.writeEndSequence();
-
- writer.writeEndSequence();
- }
-
- private static void encodeChange(final ASN1Writer writer, final Modification change)
- throws IOException {
- writer.writeStartSequence();
- writer.writeEnumerated(change.getModificationType().intValue());
- encodeAttribute(writer, change.getAttribute());
- writer.writeEndSequence();
- }
-
- private static void encodeMessageFooter(final ASN1Writer writer, final Request request)
- throws IOException {
- final List<Control> controls = request.getControls();
- if (!controls.isEmpty()) {
- writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
- for (final Control control : controls) {
- encodeControl(writer, control);
- }
- writer.writeEndSequence();
- }
-
- writer.writeEndSequence();
- }
-
- private static void encodeMessageFooter(final ASN1Writer writer, final Response response)
- throws IOException {
- final List<Control> controls = response.getControls();
- if (!controls.isEmpty()) {
- writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
- for (final Control control : controls) {
- encodeControl(writer, control);
- }
- writer.writeEndSequence();
- }
-
- writer.writeEndSequence();
- }
-
- private static void encodeMessageHeader(final ASN1Writer writer, final int messageID)
- throws IOException {
- writer.writeStartSequence();
- writer.writeInteger(messageID);
- }
-
- private static void encodeResultFooter(final ASN1Writer writer) throws IOException {
- writer.writeEndSequence();
- }
-
- private static void encodeResultHeader(final ASN1Writer writer, final byte typeTag,
- final Result rawMessage) throws IOException {
- writer.writeStartSequence(typeTag);
- writer.writeEnumerated(rawMessage.getResultCode().intValue());
- writer.writeOctetString(rawMessage.getMatchedDN());
- writer.writeOctetString(rawMessage.getDiagnosticMessage());
-
- final List<String> referralURIs = rawMessage.getReferralURIs();
- if (!referralURIs.isEmpty()) {
- writer.writeStartSequence(TYPE_REFERRAL_SEQUENCE);
- for (final String s : referralURIs) {
- writer.writeOctetString(s);
- }
- writer.writeEndSequence();
- }
- }
-
- @Override
- public void abandonRequest(final ASN1Writer writer, final int messageID,
- final AbandonRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP ABANDON REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeInteger(OP_TYPE_ABANDON_REQUEST, request.getRequestID());
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void addRequest(final ASN1Writer writer, final int messageID, final AddRequest request)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP ADD REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_ADD_REQUEST);
- writer.writeOctetString(request.getName().toString());
-
- // Write the attributes
- writer.writeStartSequence();
- for (final Attribute attr : request.getAllAttributes()) {
- encodeAttribute(writer, attr);
- }
- writer.writeEndSequence();
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void addResult(final ASN1Writer writer, final int messageID, final Result result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP ADD RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_ADD_RESPONSE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void bindRequest(final ASN1Writer writer, final int messageID, final int version,
- final GenericBindRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP BIND REQUEST(messageID={}, auth=0x{}, request={})",
- messageID, byteToHex(request.getAuthenticationType()), request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
-
- writer.writeInteger(version);
- writer.writeOctetString(request.getName());
- writer.writeOctetString(request.getAuthenticationType(), request.getAuthenticationValue());
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void bindResult(final ASN1Writer writer, final int messageID, final BindResult result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP BIND RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_BIND_RESPONSE, result);
-
- final ByteString saslCredentials = result.getServerSASLCredentials();
- if (saslCredentials != null && saslCredentials.length() > 0) {
- writer.writeOctetString(TYPE_SERVER_SASL_CREDENTIALS, result.getServerSASLCredentials());
- }
-
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void compareRequest(final ASN1Writer writer, final int messageID,
- final CompareRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP COMPARE REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_COMPARE_REQUEST);
- writer.writeOctetString(request.getName().toString());
-
- writer.writeStartSequence();
- writer.writeOctetString(request.getAttributeDescription().toString());
- writer.writeOctetString(request.getAssertionValue());
- writer.writeEndSequence();
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void compareResult(final ASN1Writer writer, final int messageID,
- final CompareResult result) throws IOException {
- IO_LOG.trace("ENCODE LDAP COMPARE RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_COMPARE_RESPONSE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void deleteRequest(final ASN1Writer writer, final int messageID,
- final DeleteRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP DELETE REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeOctetString(OP_TYPE_DELETE_REQUEST, request.getName().toString());
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void deleteResult(final ASN1Writer writer, final int messageID, final Result result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP DELETE RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_DELETE_RESPONSE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public <R extends ExtendedResult> void extendedRequest(final ASN1Writer writer,
- final int messageID, final ExtendedRequest<R> request) throws IOException {
- IO_LOG.trace("ENCODE LDAP EXTENDED REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_EXTENDED_REQUEST);
- writer.writeOctetString(TYPE_EXTENDED_REQUEST_OID, request.getOID());
-
- final ByteString requestValue = request.getValue();
- if (requestValue != null) {
- writer.writeOctetString(TYPE_EXTENDED_REQUEST_VALUE, requestValue);
- }
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void extendedResult(final ASN1Writer writer, final int messageID,
- final ExtendedResult result) throws IOException {
- IO_LOG.trace("ENCODE LDAP EXTENDED RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_EXTENDED_RESPONSE, result);
-
- final String responseName = result.getOID();
- final ByteString responseValue = result.getValue();
-
- if (responseName != null) {
- writer.writeOctetString(TYPE_EXTENDED_RESPONSE_OID, responseName);
- }
-
- if (responseValue != null) {
- writer.writeOctetString(TYPE_EXTENDED_RESPONSE_VALUE, responseValue);
- }
-
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void intermediateResponse(final ASN1Writer writer, final int messageID,
- final IntermediateResponse response) throws IOException {
- IO_LOG.trace("ENCODE LDAP INTERMEDIATE RESPONSE(messageID={}, response={})", messageID, response);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
-
- final String responseName = response.getOID();
- final ByteString responseValue = response.getValue();
-
- if (responseName != null) {
- writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_OID, response.getOID());
- }
-
- if (responseValue != null) {
- writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE, response.getValue());
- }
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, response);
- }
-
- @Override
- public void modifyDNRequest(final ASN1Writer writer, final int messageID,
- final ModifyDNRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP MODIFY DN REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
- writer.writeOctetString(request.getName().toString());
- writer.writeOctetString(request.getNewRDN().toString());
- writer.writeBoolean(request.isDeleteOldRDN());
-
- final DN newSuperior = request.getNewSuperior();
- if (newSuperior != null) {
- writer.writeOctetString(TYPE_MODIFY_DN_NEW_SUPERIOR, newSuperior.toString());
- }
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void modifyDNResult(final ASN1Writer writer, final int messageID, final Result result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP MODIFY DN RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_MODIFY_DN_RESPONSE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void modifyRequest(final ASN1Writer writer, final int messageID,
- final ModifyRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP MODIFY REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_MODIFY_REQUEST);
- writer.writeOctetString(request.getName().toString());
-
- writer.writeStartSequence();
- for (final Modification change : request.getModifications()) {
- encodeChange(writer, change);
- }
- writer.writeEndSequence();
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void modifyResult(final ASN1Writer writer, final int messageID, final Result result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP MODIFY RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_MODIFY_RESPONSE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void searchRequest(final ASN1Writer writer, final int messageID,
- final SearchRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP SEARCH REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_SEARCH_REQUEST);
- writer.writeOctetString(request.getName().toString());
- writer.writeEnumerated(request.getScope().intValue());
- writer.writeEnumerated(request.getDereferenceAliasesPolicy().intValue());
- writer.writeInteger(request.getSizeLimit());
- writer.writeInteger(request.getTimeLimit());
- writer.writeBoolean(request.isTypesOnly());
- LDAPUtils.encodeFilter(writer, request.getFilter());
-
- writer.writeStartSequence();
- for (final String attribute : request.getAttributes()) {
- writer.writeOctetString(attribute);
- }
- writer.writeEndSequence();
-
- writer.writeEndSequence();
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void searchResult(final ASN1Writer writer, final int messageID, final Result result)
- throws IOException {
- IO_LOG.trace("ENCODE LDAP SEARCH RESULT(messageID={}, result={})", messageID, result);
- encodeMessageHeader(writer, messageID);
- encodeResultHeader(writer, OP_TYPE_SEARCH_RESULT_DONE, result);
- encodeResultFooter(writer);
- encodeMessageFooter(writer, result);
- }
-
- @Override
- public void searchResultEntry(final ASN1Writer writer, final int messageID,
- final SearchResultEntry entry) throws IOException {
- IO_LOG.trace("ENCODE LDAP SEARCH RESULT ENTRY(messageID={}, entry={})", messageID, entry);
- encodeMessageHeader(writer, messageID);
- encodeEntry(writer, entry);
- encodeMessageFooter(writer, entry);
- }
-
- @Override
- public void searchResultReference(final ASN1Writer writer, final int messageID,
- final SearchResultReference reference) throws IOException {
- IO_LOG.trace("ENCODE LDAP SEARCH RESULT REFERENCE(messageID={}, reference={})", messageID, reference);
- encodeMessageHeader(writer, messageID);
- writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
- for (final String url : reference.getURIs()) {
- writer.writeOctetString(url);
- }
- writer.writeEndSequence();
- encodeMessageFooter(writer, reference);
- }
-
- @Override
- public void unbindRequest(final ASN1Writer writer, final int messageID,
- final UnbindRequest request) throws IOException {
- IO_LOG.trace("ENCODE LDAP UNBIND REQUEST(messageID={}, request={})", messageID, request);
- encodeMessageHeader(writer, messageID);
- writer.writeNull(OP_TYPE_UNBIND_REQUEST);
- encodeMessageFooter(writer, request);
- }
-
- @Override
- public void unrecognizedMessage(final ASN1Writer writer, final int messageID,
- final byte messageTag, final ByteString messageBytes) throws IOException {
- IO_LOG.trace("ENCODE LDAP UNKNOWN MESSAGE(messageID={}, messageTag={}, messageBytes={})",
- messageID, StaticUtils.byteToHex(messageTag), messageBytes);
- encodeMessageHeader(writer, messageID);
- writer.writeOctetString(messageTag, messageBytes);
- writer.writeEndSequence();
- }
-}
diff --git a/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
index dcb54bb..3c21b45 100644
--- a/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
+++ b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions copyright 2011 ForgeRock AS
+ * Portions copyright 2011-2013 ForgeRock AS
*/
package com.forgerock.opendj.grizzly;
@@ -43,7 +43,7 @@
*/
public class ASN1BufferWriterTestCase extends ASN1WriterTestCase {
- private final ASN1BufferWriter writer = ASN1BufferWriter.getWriter();
+ private final ASN1BufferWriter writer = new ASN1BufferWriter();
@Override
protected byte[] getEncodedBytes() throws IOException, DecodeException {
diff --git a/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java
index a77e2bd..a6b1d6a 100644
--- a/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java
+++ b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java
@@ -102,7 +102,7 @@
connection.searchAsync(request, null, handler);
// Pass in a time which is guaranteed to trigger expiration.
- connection.cancelExpiredRequests(System.currentTimeMillis() + 1000000);
+ connection.handleTimeout(System.currentTimeMillis() + 1000000);
if (isPersistentSearch) {
verifyZeroInteractions(handler);
} else {
diff --git a/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPReaderWriterTestCase.java b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPReaderWriterTestCase.java
new file mode 100644
index 0000000..029c2ac
--- /dev/null
+++ b/opendj3/opendj-grizzly/src/test/java/com/forgerock/opendj/grizzly/GrizzlyLDAPReaderWriterTestCase.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.forgerock.opendj.asn1.ASN1Reader;
+import org.forgerock.opendj.asn1.ASN1Writer;
+import org.forgerock.opendj.io.LDAPReader;
+import org.forgerock.opendj.io.LDAPReaderWriterTestCase;
+import org.forgerock.opendj.io.LDAPWriter;
+import org.forgerock.opendj.ldap.LDAPOptions;
+import org.glassfish.grizzly.memory.HeapMemoryManager;
+
+/**
+ * Tests for LDAPWriter / LDAPReader classes using specific implementations of
+ * ASN1 writer and ASN1 reader with Grizzly.
+ */
+public class GrizzlyLDAPReaderWriterTestCase extends LDAPReaderWriterTestCase {
+
+ @Override
+ protected LDAPWriter<? extends ASN1Writer> getLDAPWriter() {
+ return GrizzlyUtils.getWriter();
+ }
+
+ @Override
+ protected LDAPReader<? extends ASN1Reader> getLDAPReader() {
+ return GrizzlyUtils.createReader(new LDAPOptions().getDecodeOptions(),
+ 0, new HeapMemoryManager());
+ }
+
+ @Override
+ protected void transferFromWriterToReader(LDAPWriter<? extends ASN1Writer> writer,
+ LDAPReader<? extends ASN1Reader> reader) {
+ ASN1BufferReader asn1Reader = (ASN1BufferReader) reader.getASN1Reader();
+ ASN1BufferWriter asn1Writer = (ASN1BufferWriter) writer.getASN1Writer();
+ asn1Reader.appendBytesRead(asn1Writer.getBuffer());
+ }
+
+}
--
Gitblit v1.10.0