/* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. */ package com.sun.opends.sdk.ldap; import static com.sun.opends.sdk.ldap.LDAPConstants.*; import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE; import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF; import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE; import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_BOOLEAN_TYPE; import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE; import java.io.IOException; import java.util.logging.Level; import org.opends.sdk.*; import org.opends.sdk.asn1.ASN1Reader; import org.opends.sdk.controls.Control; import org.opends.sdk.controls.GenericControl; import org.opends.sdk.requests.*; import org.opends.sdk.responses.*; import org.opends.sdk.schema.Schema; import com.sun.opends.sdk.util.StaticUtils; /** * Static methods for decoding LDAP messages. */ final class LDAPReader { static SearchResultEntry decodeEntry(final ASN1Reader reader, final DecodeOptions options) throws IOException { Entry entry; reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY); try { final String dnString = reader.readOctetStringAsString(); final Schema schema = options.getSchemaResolver().resolveSchema(dnString); DN dn; try { dn = DN.valueOf(dnString, schema); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } entry = options.getEntryFactory().newEntry(dn); reader.readStartSequence(); try { while (reader.hasNextElement()) { reader.readStartSequence(); try { final String ads = reader.readOctetStringAsString(); AttributeDescription ad; try { ad = AttributeDescription.valueOf(ads, schema); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } final Attribute attribute = options.getAttributeFactory() .newAttribute(ad); reader.readStartSet(); try { while (reader.hasNextElement()) { attribute.add(reader.readOctetString()); } entry.addAttribute(attribute); } finally { reader.readEndSet(); } } finally { reader.readEndSequence(); } } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } return Responses.newSearchResultEntry(entry); } private final DecodeOptions options; LDAPReader(final DecodeOptions options) { this.options = options; } /** * Decodes the elements from the provided ASN.1 reader as an LDAP message. * * @param

* The type of {@code param}. * @param reader * The ASN.1 reader. * @param handler * The LDAPMessageHandler that will handle a decoded * message. * @param param * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */

void decode(final ASN1Reader reader, final LDAPMessageHandler

handler, final P param) throws IOException { reader.readStartSequence(); try { final int messageID = (int) reader.readInteger(); decodeProtocolOp(reader, messageID, handler, param); } finally { reader.readEndSequence(); } } /** * 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 LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeAbandonRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { final int msgToAbandon = (int) reader.readInteger(OP_TYPE_ABANDON_REQUEST); final AbandonRequest message = Requests.newAbandonRequest(msgToAbandon); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP ABANDON REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.abandonRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP add request * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeAddRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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); entry = options.getEntryFactory().newEntry(dn); reader.readStartSequence(); try { while (reader.hasNextElement()) { reader.readStartSequence(); try { final String ads = reader.readOctetStringAsString(); final AttributeDescription ad = decodeAttributeDescription(ads, schema); final Attribute attribute = options.getAttributeFactory() .newAttribute(ad); reader.readStartSet(); try { while (reader.hasNextElement()) { attribute.add(reader.readOctetString()); } entry.addAttribute(attribute); } finally { reader.readEndSet(); } } finally { reader.readEndSequence(); } } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } final AddRequest message = Requests.newAddRequest(entry); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP ADD REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.addRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an add response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeAddResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { Result message; reader.readStartSequence(OP_TYPE_ADD_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String .format("DECODE LDAP ADD RESULT(messageID=%d, result=%s)", messageID, message)); } handler.addResult(p, messageID, message); } private AttributeDescription decodeAttributeDescription( final String attributeDescription, final Schema schema) throws DecodeException { try { return AttributeDescription.valueOf(attributeDescription, schema); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } } /** * Decodes the elements from the provided ASN.1 read as an LDAP bind request * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeBindRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { reader.readStartSequence(OP_TYPE_BIND_REQUEST); try { final int protocolVersion = (int) reader.readInteger(); final String authName = reader.readOctetStringAsString(); final byte authType = reader.peekType(); final ByteString authBytes = reader.readOctetString(authType); final GenericBindRequest request = Requests.newGenericBindRequest( authName, authType, authBytes); decodeControls(reader, request); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP BIND REQUEST(messageID=%d, auth=0x%x, request=%s)", messageID, request.getAuthenticationType(), request)); } handler.bindRequest(p, messageID, protocolVersion, request); } finally { reader.readEndSequence(); } } /** * Decodes the elements from the provided ASN.1 reader as a bind response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeBindResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { BindResult message; reader.readStartSequence(OP_TYPE_BIND_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newBindResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); if (reader.hasNextElement() && (reader.peekType() == TYPE_SERVER_SASL_CREDENTIALS)) { message.setServerSASLCredentials(reader .readOctetString(TYPE_SERVER_SASL_CREDENTIALS)); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP BIND RESULT(messageID=%d, result=%s)", messageID, message)); } handler.bindResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP compare * request protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeCompareRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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); reader.readStartSequence(); try { final String ads = reader.readOctetStringAsString(); final AttributeDescription ad = decodeAttributeDescription(ads, schema); final ByteString assertionValue = reader.readOctetString(); message = Requests.newCompareRequest(dn, ad, assertionValue); } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP COMPARE REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.compareRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a compare response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeCompareResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { CompareResult message; reader.readStartSequence(OP_TYPE_COMPARE_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newCompareResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP COMPARE RESULT(messageID=%d, result=%s)", messageID, message)); } handler.compareResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP control. * * @param 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 { String oid; boolean isCritical; ByteString value; reader.readStartSequence(); try { oid = reader.readOctetStringAsString(); isCritical = false; value = null; if (reader.hasNextElement() && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE)) { isCritical = reader.readBoolean(); } if (reader.hasNextElement() && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE)) { value = reader.readOctetString(); } } finally { reader.readEndSequence(); } final Control c = GenericControl.newControl(oid, isCritical, value); request.addControl(c); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP control. * * @param 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 { String oid; boolean isCritical; ByteString value; reader.readStartSequence(); try { oid = reader.readOctetStringAsString(); isCritical = false; value = null; if (reader.hasNextElement() && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE)) { isCritical = reader.readBoolean(); } if (reader.hasNextElement() && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE)) { value = reader.readOctetString(); } } finally { reader.readEndSequence(); } final Control c = GenericControl.newControl(oid, isCritical, value); response.addControl(c); } /** * Decodes the elements from the provided ASN.1 reader as a set of controls. * * @param 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 { if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE)) { reader.readStartSequence(TYPE_CONTROL_SEQUENCE); try { while (reader.hasNextElement()) { decodeControl(reader, request); } } finally { reader.readEndSequence(); } } } /** * Decodes the elements from the provided ASN.1 reader as a set of controls. * * @param 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) throws IOException { if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE)) { reader.readStartSequence(TYPE_CONTROL_SEQUENCE); try { while (reader.hasNextElement()) { decodeControl(reader, response); } } finally { reader.readEndSequence(); } } } /** * Decodes the elements from the provided ASN.1 reader as an LDAP delete * request protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeDeleteRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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 DeleteRequest message = Requests.newDeleteRequest(dn); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP DELETE REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.deleteRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a delete response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeDeleteResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { Result message; reader.readStartSequence(OP_TYPE_DELETE_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP DELETE RESULT(messageID=%d, result=%s)", messageID, message)); } handler.deleteResult(p, messageID, message); } private DN decodeDN(final String dn, final Schema schema) throws DecodeException { try { return DN.valueOf(dn, schema); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } } /** * Decodes the elements from the provided ASN.1 reader as an LDAP extended * request protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeExtendedRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { String oid; ByteString value; reader.readStartSequence(OP_TYPE_EXTENDED_REQUEST); try { oid = reader.readOctetStringAsString(TYPE_EXTENDED_REQUEST_OID); value = null; if (reader.hasNextElement() && (reader.peekType() == TYPE_EXTENDED_REQUEST_VALUE)) { value = reader.readOctetString(TYPE_EXTENDED_REQUEST_VALUE); } } finally { reader.readEndSequence(); } final GenericExtendedRequest message = Requests.newGenericExtendedRequest( oid, value); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP EXTENDED REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.extendedRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a extended response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeExtendedResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { GenericExtendedResult message; reader.readStartSequence(OP_TYPE_EXTENDED_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newGenericExtendedResult(resultCode).setMatchedDN( matchedDN).setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); if (reader.hasNextElement() && (reader.peekType() == TYPE_EXTENDED_RESPONSE_OID)) { message.setOID(reader .readOctetStringAsString(TYPE_EXTENDED_RESPONSE_OID)); } if (reader.hasNextElement() && (reader.peekType() == TYPE_EXTENDED_RESPONSE_VALUE)) { message.setValue(reader.readOctetString(TYPE_EXTENDED_RESPONSE_VALUE)); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP EXTENDED RESULT(messageID=%d, result=%s)", messageID, message)); } handler.extendedResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP intermediate * response protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeIntermediateResponse(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { GenericIntermediateResponse message; reader.readStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE); try { message = Responses.newGenericIntermediateResponse(); if (reader.hasNextElement() && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_OID)) { message.setOID(reader .readOctetStringAsString(TYPE_INTERMEDIATE_RESPONSE_OID)); } if (reader.hasNextElement() && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_VALUE)) { message.setValue(reader .readOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE)); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP INTERMEDIATE RESPONSE(messageID=%d, response=%s)", messageID, message)); } handler.intermediateResponse(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a modify DN request * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeModifyDNRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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 String newRDNString = reader.readOctetStringAsString(); final RDN newRDN = decodeRDN(newRDNString, schema); message = Requests.newModifyDNRequest(dn, newRDN); message.setDeleteOldRDN(reader.readBoolean()); 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); message.setNewSuperior(newSuperior); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP MODIFY DN REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.modifyDNRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a modify DN response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeModifyDNResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { Result message; reader.readStartSequence(OP_TYPE_MODIFY_DN_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP MODIFY DN RESULT(messageID=%d, result=%s)", messageID, message)); } handler.modifyDNResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP modify * request protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeModifyRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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); message = Requests.newModifyRequest(dn); reader.readStartSequence(); try { while (reader.hasNextElement()) { reader.readStartSequence(); try { final int typeIntValue = reader.readEnumerated(); final ModificationType type = ModificationType .valueOf(typeIntValue); if (type == null) { throw DecodeException .error(ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE .get(typeIntValue)); } reader.readStartSequence(); try { final String ads = reader.readOctetStringAsString(); final AttributeDescription ad = decodeAttributeDescription(ads, schema); final Attribute attribute = options.getAttributeFactory() .newAttribute(ad); reader.readStartSet(); try { while (reader.hasNextElement()) { attribute.add(reader.readOctetString()); } message.addModification(new Modification(type, attribute)); } finally { reader.readEndSet(); } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP MODIFY REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.modifyRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a modify response * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeModifyResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { Result message; reader.readStartSequence(OP_TYPE_MODIFY_RESPONSE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP MODIFY RESULT(messageID=%d, result=%s)", messageID, message)); } handler.modifyResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeProtocolOp(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { final byte type = reader.peekType(); switch (type) { case OP_TYPE_UNBIND_REQUEST: // 0x42 decodeUnbindRequest(reader, messageID, handler, p); break; case 0x43: // 0x43 case 0x44: // 0x44 case 0x45: // 0x45 case 0x46: // 0x46 case 0x47: // 0x47 case 0x48: // 0x48 case 0x49: // 0x49 handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_DELETE_REQUEST: // 0x4A decodeDeleteRequest(reader, messageID, handler, p); break; case 0x4B: // 0x4B case 0x4C: // 0x4C case 0x4D: // 0x4D case 0x4E: // 0x4E case 0x4F: // 0x4F handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_ABANDON_REQUEST: // 0x50 decodeAbandonRequest(reader, messageID, handler, p); break; case 0x51: // 0x51 case 0x52: // 0x52 case 0x53: // 0x53 case 0x54: // 0x54 case 0x55: // 0x55 case 0x56: // 0x56 case 0x57: // 0x57 case 0x58: // 0x58 case 0x59: // 0x59 case 0x5A: // 0x5A case 0x5B: // 0x5B case 0x5C: // 0x5C case 0x5D: // 0x5D case 0x5E: // 0x5E case 0x5F: // 0x5F handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_BIND_REQUEST: // 0x60 decodeBindRequest(reader, messageID, handler, p); break; case OP_TYPE_BIND_RESPONSE: // 0x61 decodeBindResult(reader, messageID, handler, p); break; case 0x62: // 0x62 handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_SEARCH_REQUEST: // 0x63 decodeSearchRequest(reader, messageID, handler, p); break; case OP_TYPE_SEARCH_RESULT_ENTRY: // 0x64 decodeSearchResultEntry(reader, messageID, handler, p); break; case OP_TYPE_SEARCH_RESULT_DONE: // 0x65 decodeSearchResult(reader, messageID, handler, p); break; case OP_TYPE_MODIFY_REQUEST: // 0x66 decodeModifyRequest(reader, messageID, handler, p); break; case OP_TYPE_MODIFY_RESPONSE: // 0x67 decodeModifyResult(reader, messageID, handler, p); break; case OP_TYPE_ADD_REQUEST: // 0x68 decodeAddRequest(reader, messageID, handler, p); break; case OP_TYPE_ADD_RESPONSE: // 0x69 decodeAddResult(reader, messageID, handler, p); break; case 0x6A: // 0x6A handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_DELETE_RESPONSE: // 0x6B decodeDeleteResult(reader, messageID, handler, p); break; case OP_TYPE_MODIFY_DN_REQUEST: // 0x6C decodeModifyDNRequest(reader, messageID, handler, p); break; case OP_TYPE_MODIFY_DN_RESPONSE: // 0x6D decodeModifyDNResult(reader, messageID, handler, p); break; case OP_TYPE_COMPARE_REQUEST: // 0x6E decodeCompareRequest(reader, messageID, handler, p); break; case OP_TYPE_COMPARE_RESPONSE: // 0x6F decodeCompareResult(reader, messageID, handler, p); break; case 0x70: // 0x70 case 0x71: // 0x71 case 0x72: // 0x72 handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_SEARCH_RESULT_REFERENCE: // 0x73 decodeSearchResultReference(reader, messageID, handler, p); break; case 0x74: // 0x74 case 0x75: // 0x75 case 0x76: // 0x76 handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; case OP_TYPE_EXTENDED_REQUEST: // 0x77 decodeExtendedRequest(reader, messageID, handler, p); break; case OP_TYPE_EXTENDED_RESPONSE: // 0x78 decodeExtendedResult(reader, messageID, handler, p); break; case OP_TYPE_INTERMEDIATE_RESPONSE: // 0x79 decodeIntermediateResponse(reader, messageID, handler, p); break; default: handler.unrecognizedMessage(p, messageID, type, reader .readOctetString(type)); break; } } private RDN decodeRDN(final String rdn, final Schema schema) throws DecodeException { try { return RDN.valueOf(rdn, schema); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } } private void decodeResponseReferrals(final ASN1Reader reader, final Result message) throws IOException { if (reader.hasNextElement() && (reader.peekType() == TYPE_REFERRAL_SEQUENCE)) { reader.readStartSequence(TYPE_REFERRAL_SEQUENCE); try { // Should have at least 1. do { message.addReferralURI((reader.readOctetStringAsString())); } while (reader.hasNextElement()); } finally { reader.readEndSequence(); } } } /** * Decodes the elements from the provided ASN.1 reader as an LDAP search * request protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeSearchRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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 int scopeIntValue = reader.readEnumerated(); final SearchScope scope = SearchScope.valueOf(scopeIntValue); if (scope == null) { throw DecodeException .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE .get(scopeIntValue)); } final int dereferencePolicyIntValue = reader.readEnumerated(); final DereferenceAliasesPolicy dereferencePolicy = DereferenceAliasesPolicy .valueOf(dereferencePolicyIntValue); if (dereferencePolicy == null) { throw DecodeException .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF .get(dereferencePolicyIntValue)); } final int sizeLimit = (int) reader.readInteger(); final int timeLimit = (int) reader.readInteger(); final boolean typesOnly = reader.readBoolean(); final Filter filter = LDAPUtils.decodeFilter(reader); message = Requests.newSearchRequest(baseDN, scope, filter); message.setDereferenceAliasesPolicy(dereferencePolicy); try { message.setTimeLimit(timeLimit); message.setSizeLimit(sizeLimit); } catch (final LocalizedIllegalArgumentException e) { throw DecodeException.error(e.getMessageObject()); } message.setTypesOnly(typesOnly); reader.readStartSequence(); try { while (reader.hasNextElement()) { message.addAttribute(reader.readOctetStringAsString()); } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP SEARCH REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.searchRequest(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a search result done * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeSearchResult(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { Result message; reader.readStartSequence(OP_TYPE_SEARCH_RESULT_DONE); try { final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated()); final String matchedDN = reader.readOctetStringAsString(); final String diagnosticMessage = reader.readOctetStringAsString(); message = Responses.newResult(resultCode).setMatchedDN(matchedDN) .setDiagnosticMessage(diagnosticMessage); decodeResponseReferrals(reader, message); } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP SEARCH RESULT(messageID=%d, result=%s)", messageID, message)); } handler.searchResult(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as an LDAP search * result entry protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeSearchResultEntry(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) 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); entry = options.getEntryFactory().newEntry(dn); reader.readStartSequence(); try { while (reader.hasNextElement()) { reader.readStartSequence(); try { final String ads = reader.readOctetStringAsString(); final AttributeDescription ad = decodeAttributeDescription(ads, schema); final Attribute attribute = options.getAttributeFactory() .newAttribute(ad); reader.readStartSet(); try { while (reader.hasNextElement()) { attribute.add(reader.readOctetString()); } entry.addAttribute(attribute); } finally { reader.readEndSet(); } } finally { reader.readEndSequence(); } } } finally { reader.readEndSequence(); } } finally { reader.readEndSequence(); } final SearchResultEntry message = Responses.newSearchResultEntry(entry); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP SEARCH RESULT ENTRY(messageID=%d, entry=%s)", messageID, message)); } handler.searchResultEntry(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 reader as a search result * reference protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeSearchResultReference(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { SearchResultReference message; reader.readStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE); try { message = Responses.newSearchResultReference(reader .readOctetStringAsString()); while (reader.hasNextElement()) { message.addURI(reader.readOctetStringAsString()); } } finally { reader.readEndSequence(); } decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP SEARCH RESULT REFERENCE(messageID=%d, reference=%s)", messageID, message)); } handler.searchResultReference(p, messageID, message); } /** * Decodes the elements from the provided ASN.1 read as an LDAP unbind request * protocol op. * * @param reader * The ASN.1 reader. * @param messageID * The decoded message ID for this message. * @param handler * The LDAPMessageHandler that will handle this decoded * message. * @param p * The parameter to pass into the LDAPMessageHandler * @throws IOException * If an error occurred while reading bytes to decode. */ private

void decodeUnbindRequest(final ASN1Reader reader, final int messageID, final LDAPMessageHandler

handler, final P p) throws IOException { UnbindRequest message; reader.readNull(OP_TYPE_UNBIND_REQUEST); message = Requests.newUnbindRequest(); decodeControls(reader, message); if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER)) { StaticUtils.DEBUG_LOG.finer(String.format( "DECODE LDAP UNBIND REQUEST(messageID=%d, request=%s)", messageID, message)); } handler.unbindRequest(p, messageID, message); } }