use of org.apache.directory.api.ldap.model.message.Control in project directory-ldap-api by apache.
the class AddControl method action.
/**
* {@inheritDoc}
*/
public void action(LdapMessageContainer<MessageDecorator<? extends Message>> container) throws DecoderException {
TLV tlv = container.getCurrentTLV();
// We have to handle the special case of a 0 length OID
if (tlv.getLength() == 0) {
String msg = I18n.err(I18n.ERR_04097_NULL_CONTROL_OID);
LOG.error(msg);
// This will generate a PROTOCOL_ERROR
throw new DecoderException(msg);
}
byte[] value = tlv.getValue().getData();
String oidValue = Strings.asciiBytesToString(value);
// The OID is encoded as a String, not an Object Id
if (!Oid.isOid(oidValue)) {
String msg = I18n.err(I18n.ERR_04098_INVALID_CONTROL_OID, oidValue);
LOG.error(msg);
// This will generate a PROTOCOL_ERROR
throw new DecoderException(msg);
}
Message message = container.getMessage();
Control control = container.getLdapCodecService().newControl(oidValue);
message.addControl(control);
// We can have an END transition
container.setGrammarEndAllowed(true);
if (IS_DEBUG) {
LOG.debug("Control OID : {}", oidValue);
}
}
use of org.apache.directory.api.ldap.model.message.Control in project directory-ldap-api by apache.
the class LdapEncoder method computeMessageLength.
/**
* Compute the LdapMessage length LdapMessage :
* <pre>
* 0x30 L1
* |
* +--> 0x02 0x0(1-4) [0..2^31-1] (MessageId)
* +--> protocolOp
* [+--> Controls]
*
* MessageId length = Length(0x02) + length(MessageId) + MessageId.length
* L1 = length(ProtocolOp)
* LdapMessage length = Length(0x30) + Length(L1) + MessageId length + L1
* </pre>
*
* @param messageDecorator the decorated Message who's length is to be encoded
*/
private int computeMessageLength(MessageDecorator<? extends Message> messageDecorator) {
// The length of the MessageId. It's the sum of
// - the tag (0x02), 1 byte
// - the length of the Id length, 1 byte
// - the Id length, 1 to 4 bytes
int ldapMessageLength = 1 + 1 + BerValue.getNbBytes(messageDecorator.getDecorated().getMessageId());
// Get the protocolOp length
ldapMessageLength += messageDecorator.computeLength();
Map<String, Control> controls = messageDecorator.getControls();
// Do the same thing for Controls, if any.
if (controls.size() > 0) {
// Controls :
// 0xA0 L3
// |
// +--> 0x30 L4
// +--> 0x30 L5
// +--> ...
// +--> 0x30 Li
// +--> ...
// +--> 0x30 Ln
//
// L3 = Length(0x30) + Length(L5) + L5
// + Length(0x30) + Length(L6) + L6
// + ...
// + Length(0x30) + Length(Li) + Li
// + ...
// + Length(0x30) + Length(Ln) + Ln
//
// LdapMessageLength = LdapMessageLength + Length(0x90)
// + Length(L3) + L3
int controlsSequenceLength = 0;
// We may have more than one control. ControlsLength is L4.
for (Control control : controls.values()) {
int controlLength = computeControlLength(control);
controlsSequenceLength += 1 + TLV.getNbBytes(controlLength) + controlLength;
}
// Computes the controls length
// 1 + Length.getNbBytes( controlsSequenceLength ) + controlsSequenceLength
messageDecorator.setControlsLength(controlsSequenceLength);
// Now, add the tag and the length of the controls length
ldapMessageLength += 1 + TLV.getNbBytes(controlsSequenceLength) + controlsSequenceLength;
}
// Store the messageLength
messageDecorator.setMessageLength(ldapMessageLength);
return 1 + ldapMessageLength + TLV.getNbBytes(ldapMessageLength);
}
use of org.apache.directory.api.ldap.model.message.Control in project directory-ldap-api by apache.
the class LdapEncoder method encodeMessage.
/**
* Generate the PDU which contains the encoded object.
*
* The generation is done in two phases :
* - first, we compute the length of each part and the
* global PDU length
* - second, we produce the PDU.
*
* <pre>
* 0x30 L1
* |
* +--> 0x02 L2 MessageId
* +--> ProtocolOp
* +--> Controls
*
* L2 = Length(MessageId)
* L1 = Length(0x02) + Length(L2) + L2 + Length(ProtocolOp) + Length(Controls)
* LdapMessageLength = Length(0x30) + Length(L1) + L1
* </pre>
*
* @param message The message to encode
* @return A ByteBuffer that contains the PDU
* @throws EncoderException If anything goes wrong.
*/
public ByteBuffer encodeMessage(Message message) throws EncoderException {
MessageDecorator<? extends Message> decorator = MessageDecorator.getDecorator(codec, message);
int length = computeMessageLength(decorator);
ByteBuffer buffer = ByteBuffer.allocate(length);
try {
try {
// The LdapMessage Sequence
buffer.put(UniversalTag.SEQUENCE.getValue());
// The length has been calculated by the computeLength method
buffer.put(TLV.getBytes(decorator.getMessageLength()));
} catch (BufferOverflowException boe) {
throw new EncoderException(I18n.err(I18n.ERR_04005), boe);
}
// The message Id
BerValue.encode(buffer, message.getMessageId());
// Add the protocolOp part
decorator.encode(buffer);
// Do the same thing for Controls, if any.
Map<String, Control> controls = decorator.getControls();
if ((controls != null) && (controls.size() > 0)) {
// Encode the controls
buffer.put((byte) LdapCodecConstants.CONTROLS_TAG);
buffer.put(TLV.getBytes(decorator.getControlsLength()));
// Encode each control
for (Control control : controls.values()) {
encodeControl(buffer, control);
// The OctetString tag if the value is not null
int controlValueLength = ((CodecControl<?>) control).computeLength();
if (controlValueLength > 0) {
buffer.put(UniversalTag.OCTET_STRING.getValue());
buffer.put(TLV.getBytes(controlValueLength));
// And now, the value
((org.apache.directory.api.ldap.codec.api.CodecControl<?>) control).encode(buffer);
}
}
}
} catch (EncoderException ee) {
throw new MessageEncoderException(message.getMessageId(), ee.getMessage(), ee);
}
buffer.flip();
return buffer;
}
use of org.apache.directory.api.ldap.model.message.Control in project directory-ldap-api by apache.
the class MessageDecorator method addControl.
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public Message addControl(Control control) {
Control decorated;
CodecControl<? extends Control> controlDecorator;
if (control instanceof ControlDecorator) {
controlDecorator = (org.apache.directory.api.ldap.codec.api.CodecControl<? extends Control>) control;
decorated = controlDecorator.getDecorated();
} else {
controlDecorator = codec.newControl(control);
decorated = control;
}
decoratedMessage.addControl(decorated);
controls.put(control.getOid(), controlDecorator);
currentControl = controlDecorator;
return this;
}
use of org.apache.directory.api.ldap.model.message.Control in project directory-ldap-api by apache.
the class EndTransactionResponseTest method testEndTransactionResponseUpdateControls.
/**
* Test the decoding of a EndTransactionResponse with updateControls
*/
@Test
public void testEndTransactionResponseUpdateControls() throws DecoderException, EncoderException {
Asn1Decoder decoder = new Asn1Decoder();
ByteBuffer bb = ByteBuffer.allocate(0xAC);
bb.put(new byte[] { // EndTransactionResponse ::= SEQUENCE {
0x30, // EndTransactionResponse ::= SEQUENCE {
(byte) 0x81, // EndTransactionResponse ::= SEQUENCE {
(byte) 0xA9, // UpdateControls
0x30, // UpdateControls
(byte) 0x81, // UpdateControls
(byte) 0xA6, // updateControl
0x30, // updateControl
0x5F, // messageID
0x02, // messageID
0x01, // messageID
0x01, // controls
0x30, // controls
0x5A, // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x1A, // controlType LDAPOID,
0x04, // controlType LDAPOID,
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '1', // criticality BOOLEAN DEFAULT FALSE,
0x01, // criticality BOOLEAN DEFAULT FALSE,
0x01, // criticality BOOLEAN DEFAULT FALSE,
(byte) 0xFF, // controlValue OCTET STRING OPTIONAL }
0x04, // controlValue OCTET STRING OPTIONAL }
0x06, 'a', 'b', 'c', 'd', 'e', 'f', // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x17, // controlType LDAPOID,
0x04, // controlType LDAPOID,
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '2', // controlValue OCTET STRING OPTIONAL }
0x04, // controlValue OCTET STRING OPTIONAL }
0x06, 'g', 'h', 'i', 'j', 'k', 'l', // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x12, // controlType LDAPOID,
0x04, // controlType LDAPOID,
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '3', // criticality BOOLEAN DEFAULT FALSE}
0x01, // criticality BOOLEAN DEFAULT FALSE}
0x01, // criticality BOOLEAN DEFAULT FALSE}
(byte) 0xFF, // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x0F, // controlType LDAPOID}
0x04, // controlType LDAPOID}
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '4', // updateControl
0x30, // updateControl
0x43, // messageID
0x02, // messageID
0x01, // messageID
0x02, // controls
0x30, // controls
0x3E, // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x17, // controlType LDAPOID,
0x04, // controlType LDAPOID,
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '2', // controlValue OCTET STRING OPTIONAL }
0x04, // controlValue OCTET STRING OPTIONAL }
0x06, 'g', 'h', 'i', 'j', 'k', 'l', // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x12, // controlType LDAPOID,
0x04, // controlType LDAPOID,
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '3', // criticality BOOLEAN DEFAULT FALSE}
0x01, // criticality BOOLEAN DEFAULT FALSE}
0x01, // criticality BOOLEAN DEFAULT FALSE}
(byte) 0xFF, // Control ::= SEQUENCE {
0x30, // Control ::= SEQUENCE {
0x0F, // controlType LDAPOID}
0x04, // controlType LDAPOID}
0x0D, '1', '.', '3', '.', '6', '.', '1', '.', '5', '.', '5', '.', '4' });
String decodedPdu = Strings.dumpBytes(bb.array());
bb.flip();
EndTransactionResponseContainer container = new EndTransactionResponseContainer();
try {
decoder.decode(bb, container);
} catch (DecoderException de) {
de.printStackTrace();
fail(de.getMessage());
}
EndTransactionResponse endTransactionResponse = container.getEndTransactionResponse();
assertEquals(-1, endTransactionResponse.getFailedMessageId());
assertEquals(2, endTransactionResponse.getUpdateControls().size());
UpdateControls updateControls1 = endTransactionResponse.getUpdateControls().get(0);
assertEquals(1, updateControls1.getMessageId());
assertNotNull(updateControls1.getControls());
assertEquals(4, updateControls1.getControls().size());
for (Control control : updateControls1.getControls()) {
switch(control.getOid()) {
case "1.3.6.1.5.5.1":
assertTrue(control.isCritical());
assertEquals("abcdef", Strings.utf8ToString(((CodecControl<?>) control).getValue()));
break;
case "1.3.6.1.5.5.2":
assertFalse(control.isCritical());
assertEquals("ghijkl", Strings.utf8ToString(((CodecControl<?>) control).getValue()));
break;
case "1.3.6.1.5.5.3":
assertTrue(control.isCritical());
assertNull(((CodecControl<?>) control).getValue());
break;
case "1.3.6.1.5.5.4":
assertFalse(control.isCritical());
assertNull(((CodecControl<?>) control).getValue());
break;
default:
fail();
break;
}
}
UpdateControls updateControls2 = endTransactionResponse.getUpdateControls().get(1);
assertEquals(2, updateControls2.getMessageId());
assertNotNull(updateControls2.getControls());
assertEquals(3, updateControls2.getControls().size());
for (Control control : updateControls2.getControls()) {
switch(control.getOid()) {
case "1.3.6.1.5.5.2":
assertFalse(control.isCritical());
assertEquals("ghijkl", Strings.utf8ToString(((CodecControl<?>) control).getValue()));
break;
case "1.3.6.1.5.5.3":
assertTrue(control.isCritical());
assertNull(((CodecControl<?>) control).getValue());
break;
case "1.3.6.1.5.5.4":
assertFalse(control.isCritical());
assertNull(((CodecControl<?>) control).getValue());
break;
default:
fail();
break;
}
}
// Check the length
assertEquals(0xAC, ((EndTransactionResponseDecorator) endTransactionResponse).computeLengthInternal());
// Check the encoding
ByteBuffer bb1 = ((EndTransactionResponseDecorator) endTransactionResponse).encodeInternal();
String encodedPdu = Strings.dumpBytes(bb1.array());
assertEquals(encodedPdu, decodedPdu);
}
Aggregations