Checkpoint commit for OPENDJ-175: Decouple OpenDJ LDAP SDK from Grizzly
Move non-specific Grizzly code to opendj-core and refactor LDAPReader and LDAPWriter.
* Add new package org.forgerock.opendj.io in opendj-core for all IO related features
** org.forgerock.opendj.asn1 classes to be moved in this io package in a future commit
* Refactor LDAPReader class
** use an ASN1Reader as field instead of passing it as arg of each method
** rename methods to readXX
** add hasMessageAvailable method
** move to org.forgerock.opendj.io package in opendj-core
* Refactor LDAPWriter class
** use an ASN1Writer as field instead of passing it as arg of each method
** rename methods to writeXX
** remove implementation of LDAPMessageHandler
** move to org.forgerock.opendj.io package in opendj-core
* Adapt GrizzlyLDAPConnection, GrizzlyLDAPConnectionFactory, GrizzlyLDAPListener,
LDAPClientFilter and LDAPServerFilter classes to changes in LDAPReader and LDAPWriter
** caching of LDAPReader per connection
** caching of LDAPWriter per thread
** new utility methods in GrizzlyUtils class to handle creation and recycling of LDAPReader and
LDAPWriter instances
* Refactor LDAPMessageHandler and AbstractLDAPMessageHandler classes
** remove user provided P parameter
** move to org.forgerock.opendj.ldap.spi package in opendj-core
* Move UnexpectedRequestException, UnexpectedResponseException and UnsupportedMessageexception classes
to org.forgerock.opendj.ldap.spi package in opendj-core
* Convert TimeoutChecker class to a generic timeout facility which is not tied to connections.
** new interface TimeoutEventListener to represent listeners on timeout event
** TimeoutChecker send callbacks to listeners instead of connections
** move to org.forgerock.opendj.ldap package in opendj-core
* Fix issues with TimeoutChecker and usage in GrizzlyLDAPConnection
** prevent negative delays
** wakeup of listeners only if timeout is > 0
* Add test case support for LDAPReader/LDAPWriter in opendj-core and
specific implementation of test case in opendj-grizzly
2 files deleted
6 files added
6 files renamed
10 files modified
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/LDAPReader.java |
| | |
| | | * 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; |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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(); |
| | |
| | | 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(); |
| | |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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); |
| | |
| | | * 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(); |
| | |
| | | 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(); |
| | | } |
| | |
| | | * 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); |
| | |
| | | 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)); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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 { |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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; |
| | |
| | | * 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; |
| | |
| | | * 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(); |
| | |
| | | * 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(); |
| | |
| | | * 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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) { |
| | |
| | | * 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; |
| | | |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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; |
| | | |
| | |
| | | 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)); |
| | | } |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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(); |
| | |
| | | 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.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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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 |
| | |
| | | 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 |
| | |
| | | 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) { |
| | |
| | | } |
| | | } |
| | | |
| | | 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); |
| | |
| | | * 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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; |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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(); |
| | |
| | | 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(); |
| | |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * 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); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | |
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/TimeoutChecker.java |
| | |
| | | * 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; |
| | |
| | | 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) { |
| | |
| | | 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. |
| | |
| | | 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); |
| | |
| | | checkerThread.start(); |
| | | } |
| | | |
| | | void addConnection(final GrizzlyLDAPConnection connection) { |
| | | connections.add(connection); |
| | | /** |
| | | * 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. |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | |
| | | } |
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/AbstractLDAPMessageHandler.java |
| | |
| | | * |
| | | * |
| | | * 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; |
| | | |
| | |
| | | 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); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedRequestException.java |
| | |
| | | * |
| | | * |
| | | * 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; |
| | | |
| | |
| | | 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()); |
| | |
| | | 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; |
| | | } |
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnexpectedResponseException.java |
| | |
| | | * |
| | | * |
| | | * 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; |
| | | |
| | |
| | | * 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()); |
| | |
| | | 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; |
| | | } |
| File was renamed from opendj3/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/UnsupportedMessageException.java |
| | |
| | | * |
| | | * |
| | | * 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; |
| | | |
| | |
| | | * 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()); |
| | |
| | | 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; |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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); |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * 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; |
| | | |
| | |
| | | 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; |
| | |
| | | /** |
| | | * 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; |
| | | |
| | |
| | | } |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * Creates a new ASN.1 writer that writes to a StreamWriter. |
| | | */ |
| | | private ASN1BufferWriter() { |
| | | ASN1BufferWriter() { |
| | | this.sequenceBuffer = this.rootBuffer = new RootSequenceBuffer(); |
| | | this.outBuffer = new RecyclableBuffer(); |
| | | } |
| | |
| | | // Do nothing |
| | | } |
| | | |
| | | /** |
| | | * Recycle the writer to allow re-use. |
| | | */ |
| | | public void recycle() { |
| | | sequenceBuffer = rootBuffer; |
| | | outBuffer.clear(); |
| | | ThreadCache.putToCache(WRITER_INDEX, this); |
| | | } |
| | | |
| | | /** |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | /** |
| | | * 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 |
| | |
| | | |
| | | 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 = |
| | |
| | | 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; |
| | |
| | | } |
| | | 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); |
| | |
| | | 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); |
| | |
| | | } |
| | | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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); |
| | |
| | | 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) { |
| | | 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); |
| | | } |
| | | } |
| | |
| | | return delay; |
| | | } |
| | | |
| | | @Override |
| | | public long getTimeout() { |
| | | return factory.getLDAPOptions().getTimeout(TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | /** |
| | | * Closes this connection, invoking event listeners as needed. |
| | | * |
| | |
| | | * 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(); |
| | | } |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | |
| | | 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); |
| | | |
| | | } |
| | |
| | | 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 = |
| | |
| | | */ |
| | | 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; |
| | | |
| | | /** |
| | |
| | | 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. |
| | |
| | | * 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 { |
| | |
| | | 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. |
| | |
| | | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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>() { |
| | | private static final class ClientResponseHandler extends AbstractLDAPMessageHandler { |
| | | |
| | | 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 FilterChainContext ctx, final int messageID, |
| | | final Result result) throws UnexpectedResponseException, IOException { |
| | | public void addResult(final int messageID, final Result result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void bindResult(final FilterChainContext ctx, final int messageID, |
| | | final BindResult result) throws UnexpectedResponseException, IOException { |
| | | public void bindResult(final int messageID, final BindResult result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | final int msgID = |
| | | ldapConnection.continuePendingBindRequest(future); |
| | | |
| | | final ASN1BufferWriter asn1Writer = |
| | | ASN1BufferWriter.getWriter(); |
| | | LDAPWriter<ASN1BufferWriter> ldapWriter = GrizzlyUtils.getWriter(); |
| | | try { |
| | | final GenericBindRequest nextRequest = |
| | | bindClient.nextBindRequest(); |
| | | new LDAPWriter().bindRequest(asn1Writer, msgID, 3, |
| | | nextRequest); |
| | | ctx.write(asn1Writer.getBuffer(), null); |
| | | ldapWriter.writeBindRequest(msgID, 3, nextRequest); |
| | | context.write(ldapWriter.getASN1Writer().getBuffer(), null); |
| | | } finally { |
| | | asn1Writer.recycle(); |
| | | GrizzlyUtils.recycleWriter(ldapWriter); |
| | | } |
| | | return; |
| | | } |
| | |
| | | // the SASL mechanism. |
| | | ldapConnection |
| | | .installFilter(new ConnectionSecurityLayerFilter(l, |
| | | ctx.getConnection().getTransport() |
| | | context.getConnection().getTransport() |
| | | .getMemoryManager())); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void compareResult(final FilterChainContext ctx, final int messageID, |
| | | final CompareResult result) throws UnexpectedResponseException, IOException { |
| | | public void compareResult(final int messageID, final CompareResult result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void deleteResult(final FilterChainContext ctx, final int messageID, |
| | | final Result result) throws UnexpectedResponseException, IOException { |
| | | public void deleteResult(final int messageID, final Result result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void extendedResult(final FilterChainContext ctx, final int messageID, |
| | | final ExtendedResult result) throws UnexpectedResponseException, |
| | | IOException { |
| | | public void extendedResult(final int messageID, final ExtendedResult result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | if (messageID == 0) { |
| | | // Unsolicited notification received. |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void intermediateResponse(final FilterChainContext ctx, final int messageID, |
| | | final IntermediateResponse response) throws UnexpectedResponseException, |
| | | IOException { |
| | | public void intermediateResponse(final int messageID, final IntermediateResponse response) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.getPendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void modifyDNResult(final FilterChainContext ctx, final int messageID, |
| | | final Result result) throws UnexpectedResponseException, IOException { |
| | | public void modifyDNResult(final int messageID, final Result result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void modifyResult(final FilterChainContext ctx, final int messageID, |
| | | final Result result) throws UnexpectedResponseException, IOException { |
| | | public void modifyResult(final int messageID, final Result result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void searchResult(final FilterChainContext ctx, final int messageID, |
| | | final Result result) throws UnexpectedResponseException, IOException { |
| | | public void searchResult(final int messageID, final Result result) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.removePendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void searchResultEntry(final FilterChainContext ctx, final int messageID, |
| | | final SearchResultEntry entry) throws UnexpectedResponseException, |
| | | IOException { |
| | | public void searchResultEntry(final int messageID, final SearchResultEntry entry) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.getPendingRequest(messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void searchResultReference(final FilterChainContext ctx, |
| | | final int messageID, final SearchResultReference reference) |
| | | public void searchResultReference(final int messageID, final SearchResultReference reference) |
| | | throws UnexpectedResponseException, IOException { |
| | | final GrizzlyLDAPConnection ldapConnection = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(context.getConnection()); |
| | | if (ldapConnection != null) { |
| | | final AbstractLDAPFutureResultImpl<?> pendingRequest = |
| | | ldapConnection.getPendingRequest(messageID); |
| | |
| | | |
| | | 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; |
| | | } |
| | | |
| | |
| | | |
| | | @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(); |
| | | } |
| | |
| | | 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); |
| | | } |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | * 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(); |
| | | } |
| | | return true; |
| | | GrizzlyUtils.recycleWriter(writer); |
| | | } |
| | | } |
| | | |
| | | private final class AddHandler extends AbstractHandler<Result> { |
| | | /** |
| | | * 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 static final class AddHandler extends AbstractHandler<Result> { |
| | | private AddHandler(final ClientContextImpl context, final int messageID) { |
| | | super(context, messageID); |
| | | } |
| | |
| | | } |
| | | |
| | | @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); |
| | | } |
| | |
| | | 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; |
| | |
| | | |
| | | @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); |
| | | } |
| | | } |
| | | |
| | |
| | | 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) { |
| | |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | } |
| | |
| | | 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); |
| | | } |
| | |
| | | } |
| | | |
| | | @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); |
| | | } |
| | |
| | | |
| | | @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); |
| | | } |
| | |
| | | } |
| | | |
| | | @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); |
| | | } |
| | |
| | | } |
| | | |
| | | @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); |
| | |
| | | |
| | | @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; |
| | | } |
| | | |
| | |
| | | |
| | | @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); |
| | | } |
| | | } |
| | | |
| | |
| | | // 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 |
| | |
| | | } |
| | | } |
| | | |
| | | private final LDAPReader ldapReader; |
| | | private final GrizzlyLDAPListener listener; |
| | | private final int maxASN1ElementSize; |
| | | private final DecodeOptions decodeOptions; |
| | | |
| | | private final AbstractLDAPMessageHandler<FilterChainContext> serverRequestHandler = |
| | | new AbstractLDAPMessageHandler<FilterChainContext>() { |
| | | private static final class ServerRequestHandler extends AbstractLDAPMessageHandler { |
| | | |
| | | private final Connection<?> connection; |
| | | private final LDAPReader<ASN1BufferReader> reader; |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * Returns the LDAP reader. |
| | | * |
| | | * @return the reader to read incoming LDAP messages |
| | | */ |
| | | public LDAPReader<ASN1BufferReader> getReader() { |
| | | return reader; |
| | | } |
| | | |
| | | @Override |
| | | public void abandonRequest(final FilterChainContext ctx, final int messageID, |
| | | final AbandonRequest request) throws UnexpectedRequestException { |
| | | public void abandonRequest(final int messageID, final AbandonRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | conn.handleAbandon(messageID, request); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void addRequest(final FilterChainContext ctx, final int messageID, |
| | | final AddRequest request) throws UnexpectedRequestException { |
| | | public void addRequest(final int messageID, final AddRequest request) throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final AddHandler handler = new AddHandler(clientContext, messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void bindRequest(final FilterChainContext ctx, final int messageID, |
| | | final int version, final GenericBindRequest request) |
| | | public void bindRequest(final int messageID, final int version, |
| | | final GenericBindRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final BindHandler handler = new BindHandler(clientContext, messageID); |
| | | final AbstractHandler<BindResult> handler = new BindHandler(clientContext, messageID); |
| | | conn.handleBind(messageID, version, request, handler, handler); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void compareRequest(final FilterChainContext ctx, final int messageID, |
| | | final CompareRequest request) throws UnexpectedRequestException { |
| | | public void compareRequest(final int messageID, final CompareRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final CompareHandler handler = new CompareHandler(clientContext, messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void deleteRequest(final FilterChainContext ctx, final int messageID, |
| | | final DeleteRequest request) throws UnexpectedRequestException { |
| | | public void deleteRequest(final int messageID, final DeleteRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final DeleteHandler handler = new DeleteHandler(clientContext, messageID); |
| | |
| | | |
| | | @Override |
| | | public <R extends ExtendedResult> void extendedRequest( |
| | | final FilterChainContext ctx, final int messageID, |
| | | final int messageID, |
| | | final ExtendedRequest<R> request) throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final ExtendedHandler<R> handler = |
| | | new ExtendedHandler<R>(clientContext, messageID); |
| | | final ExtendedHandler<R> handler = new ExtendedHandler<R>(clientContext, messageID); |
| | | conn.handleExtendedRequest(messageID, request, handler, handler); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void modifyDNRequest(final FilterChainContext ctx, final int messageID, |
| | | final ModifyDNRequest request) throws UnexpectedRequestException { |
| | | public void modifyDNRequest(final int messageID, final ModifyDNRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final ModifyDNHandler handler = |
| | | new ModifyDNHandler(clientContext, messageID); |
| | | final ModifyDNHandler handler = new ModifyDNHandler(clientContext, messageID); |
| | | conn.handleModifyDN(messageID, request, handler, handler); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void modifyRequest(final FilterChainContext ctx, final int messageID, |
| | | final ModifyRequest request) throws UnexpectedRequestException { |
| | | public void modifyRequest(final int messageID, final ModifyRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final ModifyHandler handler = new ModifyHandler(clientContext, messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void searchRequest(final FilterChainContext ctx, final int messageID, |
| | | final SearchRequest request) throws UnexpectedRequestException { |
| | | public void searchRequest(final int messageID, final SearchRequest request) |
| | | throws UnexpectedRequestException { |
| | | final ClientContextImpl clientContext = |
| | | LDAP_CONNECTION_ATTR.get(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.get(connection); |
| | | if (clientContext != null) { |
| | | final ServerConnection<Integer> conn = clientContext.getServerConnection(); |
| | | final SearchHandler handler = new SearchHandler(clientContext, messageID); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void unbindRequest(final FilterChainContext ctx, final int messageID, |
| | | final UnbindRequest request) { |
| | | 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(ctx.getConnection()); |
| | | LDAP_CONNECTION_ATTR.remove(connection); |
| | | if (clientContext != null) { |
| | | clientContext.handleClose(messageID, request); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void unrecognizedMessage(final FilterChainContext ctx, final int messageID, |
| | | final byte messageTag, final ByteString messageBytes) { |
| | | exceptionOccurred(ctx, new UnsupportedMessageException(messageID, messageTag, |
| | | public void unrecognizedMessage(final int messageID, final byte messageTag, |
| | | final ByteString messageBytes) { |
| | | exceptionOccurred(connection, new UnsupportedMessageException(messageID, messageTag, |
| | | messageBytes)); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | LDAPServerFilter(final GrizzlyLDAPListener listener, final LDAPReader ldapReader, |
| | | /** |
| | | * 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); |
| | | } |
| | |
| | | |
| | | @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); |
| | |
| | | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011 ForgeRock AS |
| | | * Portions copyright 2011-2013 ForgeRock AS |
| | | */ |
| | | |
| | | package com.forgerock.opendj.grizzly; |
| | |
| | | */ |
| | | public class ASN1BufferWriterTestCase extends ASN1WriterTestCase { |
| | | |
| | | private final ASN1BufferWriter writer = ASN1BufferWriter.getWriter(); |
| | | private final ASN1BufferWriter writer = new ASN1BufferWriter(); |
| | | |
| | | @Override |
| | | protected byte[] getEncodedBytes() throws IOException, DecodeException { |
| | |
| | | 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 { |
| New file |
| | |
| | | /* |
| | | * 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()); |
| | | } |
| | | |
| | | } |