A bit more about it.
Here is the code we are using for the AddRequest encoding :
public final class AddRequestDecorator extends
AbstractSingleReplyRequestDecorator<AddRequest> implements
AddRequest
{
/** The add request length */
private int addRequestLength;
/** The Entry length */
private int entryLength;
/** The list of all attributes length */
private List<Integer> attributesLength;
/** The list of all attributes Id bytes */
private List<byte[]> attributeIds;
/** The list of all vals length */
private List<Integer> valuesLength;
/** The bytes containing the Dn */
private byte[] dnBytes;
...
public int computeLength()
{
AddRequest addRequest = getDecorated();
Entry entry = addRequest.getEntry();
if ( entry == null )
{
throw new IllegalArgumentException( I18n.err(
I18n.ERR_05002_ENTRY_NULL_VALUE ) );
}
dnBytes = Strings.getBytesUtf8( entry.getDn().getName() );
int dnLen = dnBytes.length;
// The entry Dn
addRequestLength = 1 + TLV.getNbBytes( dnLen ) + dnLen;
// The attributes sequence
entryLength = 0;
if ( entry.size() != 0 )
{
attributesLength = new LinkedList<>();
attributeIds = new LinkedList<>();
valuesLength = new LinkedList<>();
// Compute the attributes length
for ( Attribute attribute : entry )
{
int localAttributeLength;
int localValuesLength;
// Get the type length
byte[] attributeIdBytes = Strings.getBytesUtf8(
attribute.getUpId() );
attributeIds.add( attributeIdBytes );
int idLength = attributeIdBytes.length;
localAttributeLength = 1 + TLV.getNbBytes( idLength ) +
idLength;
// The values
if ( attribute.size() != 0 )
{
localValuesLength = 0;
for ( Value value : attribute )
{
if ( value.getBytes() == null )
{
localValuesLength += 1 + 1;
}
else
{
int valueLength = value.getBytes().length;
localValuesLength += 1 + TLV.getNbBytes(
valueLength ) + valueLength;
}
}
localAttributeLength += 1 + TLV.getNbBytes(
localValuesLength ) + localValuesLength;
}
else
{
// No value : we still have to store the
encapsulating Sequence
localValuesLength = 1 + 1;
localAttributeLength += 1 + 1 + localValuesLength;
}
// add the attribute length to the attributes length
entryLength += 1 + TLV.getNbBytes( localAttributeLength
) + localAttributeLength;
attributesLength.add( localAttributeLength );
valuesLength.add( localValuesLength );
}
}
addRequestLength += 1 + TLV.getNbBytes( entryLength ) + entryLength;
// Return the result.
return 1 + TLV.getNbBytes( addRequestLength ) + addRequestLength;
}
...
public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
{
try
{
// The AddRequest Tag
buffer.put( LdapCodecConstants.ADD_REQUEST_TAG );
buffer.put( TLV.getBytes( addRequestLength ) );
// The entry
BerValue.encode( buffer, dnBytes );
// The attributes sequence
buffer.put( UniversalTag.SEQUENCE.getValue() );
buffer.put( TLV.getBytes( entryLength ) );
// The partial attribute list
Entry entry = getEntry();
if ( entry.size() != 0 )
{
int attributeNumber = 0;
// Compute the attributes length
for ( Attribute attribute : entry )
{
// The attributes list sequence
buffer.put( UniversalTag.SEQUENCE.getValue() );
int localAttributeLength = attributesLength.get(
attributeNumber );
buffer.put( TLV.getBytes( localAttributeLength ) );
// The attribute type
BerValue.encode( buffer, attributeIds.get(
attributeNumber ) );
// The values
buffer.put( UniversalTag.SET.getValue() );
int localValuesLength = valuesLength.get(
attributeNumber );
buffer.put( TLV.getBytes( localValuesLength ) );
if ( attribute.size() != 0 )
{
for ( Value value : attribute )
{
BerValue.encode( buffer, value.getBytes() );
}
}
else
{
BerValue.encode( buffer, Strings.EMPTY_BYTES );
}
// Go to the next attribute number
attributeNumber++;
}
}
return buffer;
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err(
I18n.ERR_08212_PDU_BUFFER_TOO_SMALL, boe.getMessage() ) );
}
}
And here the new encoder code :
public void encode( Asn1Buffer buffer )
{
int addRequestPos = buffer.getPos();
// The partial attribute list
Entry entry = getEntry();
if ( entry.size() != 0 )
{
// Compute the attributes length
for ( Attribute attribute : entry )
{
// The values
int attributePos = buffer.getPos();
if ( attribute.size() != 0 )
{
for ( Value value : attribute )
{
BerValue.encodeOctetString( buffer,
value.getBytes() );
}
}
else
{
BerValue.encodeOctetString( buffer,
Strings.EMPTY_BYTES );
}
TLV.encodeLength( buffer, attributePos - buffer.getPos() );
buffer.put( UniversalTag.SET.getValue() );
// The attribute ID
BerValue.encodeOctetString( buffer,
Strings.getBytesUtf8( attribute.getUpId() ) );
// The attributes list sequence
TLV.encodeLength( buffer, attributePos - buffer.getPos() );
buffer.put( UniversalTag.SEQUENCE.getValue() );
}
}
// The attributes sequence
TLV.encodeLength( buffer, addRequestPos - buffer.getPos() );
buffer.put( UniversalTag.SEQUENCE.getValue() );
// The entry DN
BerValue.encodeOctetString( buffer, dnBytes );
// The AddRequest Tag
TLV.encodeLength( buffer, addRequestPos - buffer.getPos() );
buffer.put( LdapCodecConstants.ADD_REQUEST_TAG );
}
I think it says it all...
--
Emmanuel Lecharny
Symas.com
directory.apache.org