/* * 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); } }