You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2006/10/02 01:07:49 UTC

svn commit: r451836 [2/11] - in /directory/branches/shared/0.9.5/ldap/src: main/java/org/apache/directory/shared/ldap/codec/ main/java/org/apache/directory/shared/ldap/codec/abandon/ main/java/org/apache/directory/shared/ldap/codec/actions/ main/java/o...

Modified: directory/branches/shared/0.9.5/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java
URL: http://svn.apache.org/viewvc/directory/branches/shared/0.9.5/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java?view=diff&rev=451836&r1=451835&r2=451836
==============================================================================
--- directory/branches/shared/0.9.5/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java (original)
+++ directory/branches/shared/0.9.5/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java Sun Oct  1 16:07:44 2006
@@ -20,17 +20,90 @@
 package org.apache.directory.shared.ldap.codec;
 
 
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+
 import org.apache.directory.shared.asn1.ber.IAsn1Container;
 import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
 import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
 import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
+import org.apache.directory.shared.asn1.ber.grammar.IAction;
 import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
 import org.apache.directory.shared.asn1.codec.DecoderException;
+import org.apache.directory.shared.asn1.primitives.OID;
+import org.apache.directory.shared.asn1.util.BooleanDecoder;
+import org.apache.directory.shared.asn1.util.BooleanDecoderException;
 import org.apache.directory.shared.asn1.util.IntegerDecoder;
 import org.apache.directory.shared.asn1.util.IntegerDecoderException;
+import org.apache.directory.shared.ldap.codec.abandon.AbandonRequest;
+import org.apache.directory.shared.ldap.codec.actions.AttributeDescAction;
+import org.apache.directory.shared.ldap.codec.actions.ControlValueAction;
+import org.apache.directory.shared.ldap.codec.actions.ControlsInitAction;
+import org.apache.directory.shared.ldap.codec.actions.ErrorMessageAction;
+import org.apache.directory.shared.ldap.codec.actions.InitAndFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitApproxMatchFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitAssertionValueFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitAttributeDescFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitAttributeDescListAction;
+import org.apache.directory.shared.ldap.codec.actions.InitEqualityMatchFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitExtensibleMatchFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitGreaterOrEqualFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitLessOrEqualFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitNotFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitOrFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitPresentFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.InitReferralsAction;
+import org.apache.directory.shared.ldap.codec.actions.InitSubstringsFilterAction;
+import org.apache.directory.shared.ldap.codec.actions.MatchedDNAction;
+import org.apache.directory.shared.ldap.codec.actions.ModifyAttributeValueAction;
+import org.apache.directory.shared.ldap.codec.actions.ReferralAction;
+import org.apache.directory.shared.ldap.codec.actions.ResponseAction;
+import org.apache.directory.shared.ldap.codec.actions.ResponseNameAction;
+import org.apache.directory.shared.ldap.codec.actions.ResultCodeAction;
+import org.apache.directory.shared.ldap.codec.actions.SearchResultAttributeValueAction;
+import org.apache.directory.shared.ldap.codec.actions.ServerSASLCredsAction;
+import org.apache.directory.shared.ldap.codec.actions.StoreAnyAction;
+import org.apache.directory.shared.ldap.codec.actions.StoreFinalAction;
+import org.apache.directory.shared.ldap.codec.actions.StoreMatchValueAction;
+import org.apache.directory.shared.ldap.codec.actions.StoreReferenceAction;
+import org.apache.directory.shared.ldap.codec.actions.StoreTypeMatchingRuleAction;
+import org.apache.directory.shared.ldap.codec.actions.ValueAction;
+import org.apache.directory.shared.ldap.codec.add.AddRequest;
+import org.apache.directory.shared.ldap.codec.add.AddResponse;
+import org.apache.directory.shared.ldap.codec.bind.BindRequest;
+import org.apache.directory.shared.ldap.codec.bind.BindResponse;
+import org.apache.directory.shared.ldap.codec.bind.SaslCredentials;
+import org.apache.directory.shared.ldap.codec.bind.SimpleAuthentication;
+import org.apache.directory.shared.ldap.codec.compare.CompareRequest;
+import org.apache.directory.shared.ldap.codec.compare.CompareResponse;
+import org.apache.directory.shared.ldap.codec.del.DelRequest;
+import org.apache.directory.shared.ldap.codec.del.DelResponse;
+import org.apache.directory.shared.ldap.codec.extended.ExtendedRequest;
+import org.apache.directory.shared.ldap.codec.extended.ExtendedResponse;
+import org.apache.directory.shared.ldap.codec.modify.ModifyRequest;
+import org.apache.directory.shared.ldap.codec.modify.ModifyResponse;
+import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNRequest;
+import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNResponse;
+import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
+import org.apache.directory.shared.ldap.codec.search.SearchRequest;
+import org.apache.directory.shared.ldap.codec.search.SearchResultDone;
+import org.apache.directory.shared.ldap.codec.search.SearchResultEntry;
+import org.apache.directory.shared.ldap.codec.search.SearchResultReference;
+import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
+import org.apache.directory.shared.ldap.codec.unbind.UnBindRequest;
+import org.apache.directory.shared.ldap.message.AddResponseImpl;
+import org.apache.directory.shared.ldap.message.BindResponseImpl;
+import org.apache.directory.shared.ldap.message.CompareResponseImpl;
+import org.apache.directory.shared.ldap.message.DeleteResponseImpl;
+import org.apache.directory.shared.ldap.message.ModifyDnResponseImpl;
+import org.apache.directory.shared.ldap.message.ModifyResponseImpl;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.directory.shared.ldap.message.SearchResponseDoneImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.Rdn;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,22 +144,22 @@
         statesEnum = LdapStatesEnum.getInstance();
 
         // Create the transitions table
-        super.transitions = new GrammarTransition[LdapStatesEnum.LAST_LDAP_MESSAGE_STATE][256];
+        super.transitions = new GrammarTransition[LdapStatesEnum.LAST_LDAP_STATE][256];
 
         // ============================================================================================
-        // LdapMessage
+        // Transition from START to LdapMessage
         // ============================================================================================
-        // LDAPMessage --> SEQUENCE { ... (Tag)
-        // We have a LDAPMessage, and the tag must be 0x30
-        super.transitions[LdapStatesEnum.LDAP_MESSAGE_TAG][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
-            LdapStatesEnum.LDAP_MESSAGE_TAG, LdapStatesEnum.LDAP_MESSAGE_VALUE, null );
-
-        // LDAPMessage --> SEQUENCE { ... (Value)
-        // Nothing to do, it's a constructed TLV. It's just a phantom transition
-        // ...
-        super.transitions[LdapStatesEnum.LDAP_MESSAGE_VALUE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
-            LdapStatesEnum.LDAP_MESSAGE_VALUE, LdapStatesEnum.LDAP_MESSAGE_ID_TAG, new GrammarAction(
-                "LdapMessage initialization" )
+        // This is the starting state :
+        // LDAPMessage --> SEQUENCE { ... 
+        //
+        // We have a LDAPMessage, and the tag must be 0x30. 
+        //
+        // The next state will be LDAP_MESSAGE_STATE
+        //
+        // We will just check that the length is not null
+        super.transitions[LdapStatesEnum.START_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.START_STATE, LdapStatesEnum.LDAP_MESSAGE_STATE, UniversalTag.SEQUENCE_TAG, 
+                new GrammarAction( "LdapMessage initialization" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -96,9 +169,10 @@
                     TLV tlv = ldapMessageContainer.getCurrentTLV();
 
                     // The Length should not be null
-                    if ( tlv.getLength().getLength() == 0 )
+                    if ( tlv.getLength() == 0 )
                     {
                         log.error( "The LdapMessage has a zero length. This is not allowed" );
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( "The LdapMessage should not be empty" );
                     }
@@ -108,26 +182,27 @@
 
                     // Then stores it into the container
                     ldapMessageContainer.setLdapMessage( ldapMessage );
-                    ldapMessageContainer.grammarEndAllowed( false );
 
                     return;
                 }
             } );
 
         // --------------------------------------------------------------------------------------------
-        // LdapMessage Message ID
+        // Transition from LdapMessage to Message ID
         // --------------------------------------------------------------------------------------------
-        // LDAPMessage --> ... MessageId ...(Tag)
-        // The tag must be 0x02. Nothing special to do.
-        super.transitions[LdapStatesEnum.LDAP_MESSAGE_ID_TAG][UniversalTag.INTEGER_TAG] = new GrammarTransition(
-            LdapStatesEnum.LDAP_MESSAGE_ID_TAG, LdapStatesEnum.LDAP_MESSAGE_ID_VALUE, null );
-
-        // LDAPMessage --> ... MessageId ...(Value)
+        // LDAPMessage --> ... MessageId ...
+        //
         // Checks that MessageId is in [0 .. 2147483647] and store the value in
         // the LdapMessage Object
+        //
         // (2147483647 = Integer.MAX_VALUE)
-        super.transitions[LdapStatesEnum.LDAP_MESSAGE_ID_VALUE][UniversalTag.INTEGER_TAG] = new GrammarTransition(
-            LdapStatesEnum.LDAP_MESSAGE_ID_VALUE, LdapStatesEnum.PROTOCOL_OP_TAG, new GrammarAction( "Store MessageId" )
+        // The next state will be MESSAGE_ID_STATE
+        //
+        // The message ID will be temporarely stored in the container, because we can't store it
+        // into an object.
+        super.transitions[LdapStatesEnum.LDAP_MESSAGE_STATE][UniversalTag.INTEGER_TAG] = 
+            new GrammarTransition(LdapStatesEnum.LDAP_MESSAGE_STATE, LdapStatesEnum.MESSAGE_ID_STATE, UniversalTag.INTEGER_TAG, 
+                new GrammarAction( "Store MessageId" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -140,7 +215,7 @@
                     TLV tlv = ldapMessageContainer.getCurrentTLV();
 
                     // The Length should not be null
-                    if ( tlv.getLength().getLength() == 0 )
+                    if ( tlv.getLength() == 0 )
                     {
                         log.error( "The messageId has a zero length. This is not allowed" );
                         
@@ -155,6 +230,7 @@
                         int messageId = IntegerDecoder.parse( value, 0, Integer.MAX_VALUE );
 
                         ldapMessage.setMessageId( messageId );
+                        ldapMessageContainer.setMessageId( messageId );
 
                         if ( IS_DEBUG )
                         {
@@ -175,6 +251,7 @@
             } );
 
         // ********************************************************************************************
+        // We have a ProtocolOp :
         // If the Tag is 0x42, then it's an UnBindRequest.
         // If the Tag is 0x4A, then it's a DelRequest.
         // If the Tag is 0x50, then it's an AbandonRequest.
@@ -195,199 +272,6233 @@
         // If the Tag is 0x73, then it's a SearchResultReference.
         // If the Tag is 0x77, then it's an ExtendedRequest.
         // If the Tag is 0x78, then it's an ExtendedResponse.
+        //
+        // We create the associated object in this transition, and store it into the container.
         // ********************************************************************************************
 
         // --------------------------------------------------------------------------------------------
-        // UnBindRequest Message.
+        // Transition from Message ID to UnBindRequest Message.
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... UnBindRequest ...
-        // unbindRequest ::= [APPLICATION 2] NULL (Tag)
+        // unbindRequest ::= [APPLICATION 2] NULL
         // We have to switch to the UnBindRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.UNBIND_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.UNBIND_REQUEST_GRAMMAR_SWITCH, null );
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.UNBIND_REQUEST_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.UNBIND_REQUEST_STATE, LdapConstants.UNBIND_REQUEST_TAG, 
+                new GrammarAction( "Unbind Request initialization" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
 
-        // --------------------------------------------------------------------------------------------
-        // DelRequest Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... DelRequest ...
-        // delRequest ::= [APPLICATION 10] LDAPDN (Tag)
-        // We have to switch to the DelRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.DEL_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.DEL_REQUEST_GRAMMAR_SWITCH, null );
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
 
-        // --------------------------------------------------------------------------------------------
-        // AbandonRequest Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... AbandonRequest ...
-        // AbandonRequest ::= [APPLICATION 16] MessageID (Tag)
-        // We have to switch to the AbandonRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.ABANDON_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.ABANDON_REQUEST_GRAMMAR_SWITCH, null );
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+                    int expectedLength = tlv.getLength();
 
-        // --------------------------------------------------------------------------------------------
-        // BindRequest Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... BindRequest ...
-        // BindRequest ::= [APPLICATION 0] SEQUENCE { ... (Tag)
-        // Nothing to do while the length is not checked.
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.BIND_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.BIND_REQUEST_GRAMMAR_SWITCH, null );
+                    // The Length should be null
+                    if ( expectedLength != 0 )
+                    {
+                        log.error( "The length of a UnBindRequest must be null, the actual value is {}", new Integer(
+                            expectedLength ) );
+                        
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( "The length of a UnBindRequest must be null" );
+                    }
+                    
+                    UnBindRequest unBindRequest = new UnBindRequest();
+                    
+                    unBindRequest.setParent( ldapMessage );
 
-        // --------------------------------------------------------------------------------------------
-        // BindResponse Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... BindResponse ...
-        // BindResponse ::= [APPLICATION 1] SEQUENCE { ... (Tag)
-        // We have to switch to the BindResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.BIND_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.BIND_RESPONSE_GRAMMAR_SWITCH, null );
+                    // And we associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( unBindRequest );
 
-        // --------------------------------------------------------------------------------------------
-        // SearchRequest Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... SearchRequest ...
-        // SearchRequest ::= [APPLICATION 3] SEQUENCE { ... (Tag)
-        // Nothing to do while the length is not checked.
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.SEARCH_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.SEARCH_REQUEST_GRAMMAR_SWITCH, null );
+                    // We can quit now
+                    ldapMessageContainer.grammarEndAllowed( true );
 
-        // --------------------------------------------------------------------------------------------
-        // SearchResultEntry Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... SearchResultEntry ...
-        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ... (Tag)
-        // Nothing to do while the length is not checked.
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.SEARCH_RESULT_ENTRY_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.SEARCH_RESULT_ENTRY_GRAMMAR_SWITCH, null );
+                    return;
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // SearchResultDone Message.
+        // transition from UnBindRequest Message to Controls.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... SearchResultDone ...
-        // SearchResultDone ::= [APPLICATION 5] SEQUENCE { ... (Tag)
-        // We have to switch to the SearchResultDone grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.SEARCH_RESULT_DONE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.SEARCH_RESULT_DONE_GRAMMAR_SWITCH, null );
+        //         unbindRequest   UnbindRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.UNBIND_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.UNBIND_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
-        // ModifyRequest Message.
+        // Transition from Message ID to DelRequest Message.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ModifyRequest ...
-        // ModifyRequest ::= [APPLICATION 6] SEQUENCE { ... (Tag)
-        // We have to switch to the ModifyRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.MODIFY_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.MODIFY_REQUEST_GRAMMAR_SWITCH, null );
+        // LdapMessage ::= ... DelRequest ...
+        // delRequest ::= [APPLICATION 10] LDAPDN
+        //
+        // We store the DN to bve deleted into the DelRequest object
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.DEL_REQUEST_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.DEL_REQUEST_STATE, LdapConstants.DEL_REQUEST_TAG, 
+                new GrammarAction( "Init del Request" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
 
-        // --------------------------------------------------------------------------------------------
-        // ModifydResponse Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ModifyResponse ...
-        // ModifyResponse ::= [APPLICATION 7] SEQUENCE { ... (Tag)
-        // We have to switch to the ModifyResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.MODIFY_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.MODIFY_RESPONSE_GRAMMAR_SWITCH, null );
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
 
-        // --------------------------------------------------------------------------------------------
-        // AddRequest Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... AddRequest ...
-        // AddRequest ::= [APPLICATION 8] SEQUENCE { ... (Tag)
-        // We have to switch to the AddRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.ADD_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.ADD_REQUEST_GRAMMAR_SWITCH, null );
+                    // We can allocate the DelRequest Object
+                    DelRequest delRequest = new DelRequest();
 
-        // --------------------------------------------------------------------------------------------
-        // AddResponse Message.
-        // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... AddResponse ...
-        // AddResponse ::= [APPLICATION 9] LDAPResult (Tag)
-        // We have to switch to the AddResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.ADD_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.ADD_RESPONSE_GRAMMAR_SWITCH, null );
+                    // And store the DN into it
+                    // Get the Value and store it in the DelRequest
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    // We have to handle the special case of a 0 length matched
+                    // DN
+                    LdapDN entry = null;
+
+                    if ( tlv.getLength() == 0 )
+                    {
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( "The entry must not be null" );
+                    }
+                    else
+                    {
+                        byte[] dnBytes = tlv.getValue().getData();
+                        
+                        try
+                        {
+                            entry = new LdapDN( dnBytes );
+                        }
+                        catch ( InvalidNameException ine )
+                        {
+                            String msg = "The DN to delete : " + StringTools.utf8ToString( dnBytes ) + 
+                                " (" + StringTools.dumpBytes( dnBytes )
+                                + ") is invalid";
+                            log.error( "{} : {}", msg, ine.getMessage() );
+                            
+                            DeleteResponseImpl response = new DeleteResponseImpl( ldapMessage.getMessageId() );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALIDDNSYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                        }
+
+                        delRequest.setEntry( entry );
+                    }
+
+                    // then we associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( delRequest );
+
+                    // We can have an END transition
+                    ldapMessageContainer.grammarEndAllowed( true );
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "Deleting DN {}", entry );
+                    }
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // DelResponse Message.
+        // transition from DelRequest Message to Controls.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... DelResponse ...
-        // DelResponse ::= [APPLICATION 11] LDAPResult (Tag)
-        // We have to switch to the DelResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.DEL_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.DEL_RESPONSE_GRAMMAR_SWITCH, null );
+        //         delRequest   DelRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.DEL_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.DEL_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
-        // ModifydDNRequest Message.
+        // Transition from Message ID to AbandonRequest Message.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ModifyDNRequest ...
-        // ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { ... (Tag)
-        // We have to switch to the ModifyDNRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.MODIFY_DN_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.MODIFY_DN_REQUEST_GRAMMAR_SWITCH, null );
+        // LdapMessage ::= ... AbandonRequest ...
+        // AbandonRequest ::= [APPLICATION 16] MessageID
+        //
+        // Create the AbandonRequest object, and store the ID in it
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ABANDON_REQUEST_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ABANDON_REQUEST_STATE, LdapConstants.ABANDON_REQUEST_TAG, 
+                new GrammarAction( "Init Abandon Request" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // The current TLV should be a integer
+                    // We get it and store it in MessageId
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    Value value = tlv.getValue();
+
+                    if ( ( value == null ) || ( value.getData() == null ) )
+                    {
+                        String msg = "The AbandonRequest messageId must not be null";
+                        log.error( msg );
+
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( msg );
+                    }
+
+                    try
+                    {
+                        int abandonnedMessageId = IntegerDecoder.parse( value, 0, Integer.MAX_VALUE );
+
+                        // Ok, the Message ID is correct. We have to store it
+                        // in the AbandonRequest Object
+                        AbandonRequest abandonRequest = new AbandonRequest();
+                        abandonRequest.setAbandonedMessageId( abandonnedMessageId );
+                        ldapMessage.setProtocolOP( abandonRequest );
+
+                        if ( IS_DEBUG )
+                        {
+                            log.debug( "AbandonMessage Id has been decoded : {}", new Integer( abandonnedMessageId ) );
+                        }
+
+                        ldapMessageContainer.grammarEndAllowed( true );
+                        return;
+                    }
+                    catch ( IntegerDecoderException ide )
+                    {
+                        log.error( "The Abandonned Message Id {} is invalid : {}. The message ID must be between (0 .. 2 147 483 647)",
+                                StringTools.dumpBytes( value.getData() ), ide.getMessage() );
+
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( ide.getMessage() );
+                    }
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // ModifydResponse Message.
+        // transition from AbandonRequest Message to Controls.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ModifyDNResponse ...
-        // ModifyDNResponse ::= [APPLICATION 13] SEQUENCE { ... (Tag)
-        // We have to switch to the ModifyDNResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.MODIFY_DN_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.MODIFY_DN_RESPONSE_GRAMMAR_SWITCH, null );
-
+        //         abandonRequest   AbandonRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.ABANDON_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ABANDON_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+        
         // --------------------------------------------------------------------------------------------
-        // CompareResquest Message.
+        // Transition from Message ID to BindRequest Message.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... CompareRequest ...
-        // CompareRequest ::= [APPLICATION 14] SEQUENCE {
-        // We have to switch to the CompareRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.COMPARE_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.COMPARE_REQUEST_GRAMMAR_SWITCH, null );
+        // LdapMessage ::= ... BindRequest ...
+        // BindRequest ::= [APPLICATION 0] SEQUENCE { ...
+        //
+        // We have to allocate a BindRequest
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_REQUEST_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_REQUEST_STATE, LdapConstants.BIND_REQUEST_TAG, 
+                new GrammarAction(
+                "Init BindRequest" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // We will check that the request is not null
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    if ( tlv.getLength() == 0 )
+                    {
+                        String msg = "The BindRequest must not be null";
+                        log.error( msg );
+                     
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( msg );
+                    }
+
+                    // Now, we can allocate the BindRequest Object
+                    ldapMessage.setProtocolOP( new BindRequest() );
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // CompareResponse Message.
+        // Transition from BindRequest to version
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... CompareResponse ...
-        // CompareResponse ::= [APPLICATION 15] LDAPResult (Tag)
-        // We have to switch to the CompareResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.COMPARE_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.COMPARE_RESPONSE_GRAMMAR_SWITCH, null );
+        // BindRequest ::= [APPLICATION 0] SEQUENCE {
+        //     version                 INTEGER (1 ..  127),
+        //     ....
+        //
+        // The Ldap version is parsed and stored into the BindRequest object
+        super.transitions[LdapStatesEnum.BIND_REQUEST_STATE][UniversalTag.INTEGER_TAG] = 
+            new GrammarTransition( LdapStatesEnum.BIND_REQUEST_STATE, LdapStatesEnum.VERSION_STATE, UniversalTag.INTEGER_TAG, 
+                new GrammarAction( "Store version" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    BindRequest bindRequestMessage = ldapMessageContainer.getLdapMessage().getBindRequest();
+
+                    // The current TLV should be a integer between 1 and 127
+                    // We get it and store it in Version
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    Value value = tlv.getValue();
+
+                    try
+                    {
+                        int version = IntegerDecoder.parse( value, 1, 127 );
+
+                        if ( IS_DEBUG )
+                        {
+                            log.debug( "Ldap version ", new Integer( version ) );
+                        }
+
+                        bindRequestMessage.setVersion( version );
+                    }
+                    catch ( IntegerDecoderException ide )
+                    {
+                        log.error( "The version {} is invalid : {}. The version must be between (0 .. 127)",
+                            StringTools.dumpBytes( value.getData() ), ide.getMessage() );
+
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( ide.getMessage() );
+                    }
 
+                    return;
+                }
+            } );
+        
         // --------------------------------------------------------------------------------------------
-        // SearchResultReference Message.
+        // Transition from version to name
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... SearchResultReference ...
-        // SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL (Tag)
-        // We have to switch to the SearchResultReference grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.SEARCH_RESULT_REFERENCE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.SEARCH_RESULT_REFERENCE_GRAMMAR_SWITCH, null );
+        // BindRequest ::= [APPLICATION 0] SEQUENCE {
+        //     ....
+        //     name                    LDAPDN,
+        //     ....
+        //
+        // The Ldap version is parsed and stored into the BindRequest object
+        super.transitions[LdapStatesEnum.VERSION_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.VERSION_STATE, LdapStatesEnum.NAME_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new GrammarAction( "Store Bind Name value" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException, InvalidNameException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    BindRequest bindRequestMessage = ldapMessage.getBindRequest();
+
+                    // Get the Value and store it in the BindRequest
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    // We have to handle the special case of a 0 length name
+                    if ( tlv.getLength() == 0 )
+                    {
+                        bindRequestMessage.setName( LdapDN.EMPTY_LDAPDN );
+                    }
+                    else
+                    {
+                        LdapDN name = LdapDN.EMPTY_LDAPDN;
+                        byte[] dnBytes = tlv.getValue().getData();
+
+                        try
+                        {
+                            name = new LdapDN( dnBytes );
+                        }
+                        catch ( InvalidNameException ine )
+                        {
+                            String msg = "Incorrect DN given : " + StringTools.utf8ToString( dnBytes ) + 
+                                " (" + StringTools.dumpBytes( dnBytes )
+                                + ") is invalid";
+                            log.error( "{} : {}", msg, ine.getMessage() );
+                        
+                            BindResponseImpl response = new BindResponseImpl( ldapMessage.getMessageId() );
+                        
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALIDDNSYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                        }
+
+                        bindRequestMessage.setName( name );
+                    }
 
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( " The Bind name is {}", bindRequestMessage.getName() );
+                    }
+
+                    return;
+                }
+            } );
+        
         // --------------------------------------------------------------------------------------------
-        // ExtendedRequest Message.
+        // Transition from name to Simple Authentication
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ExtendedRequest ...
-        // ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
-        // We have to switch to the ExtendedRequest grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.EXTENDED_REQUEST_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.EXTENDED_REQUEST_GRAMMAR_SWITCH, null );
+        // BindRequest ::= [APPLICATION 0] SEQUENCE {
+        //     ....
+        //     authentication          AuthenticationChoice }
+        //
+        // AuthenticationChoice ::= CHOICE {
+        //     simple                  [0] OCTET STRING,
+        //     ...
+        //
+        // We have to create an Authentication Object to store the credentials.
+        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SIMPLE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.NAME_STATE, LdapStatesEnum.SIMPLE_STATE, LdapConstants.BIND_REQUEST_SIMPLE_TAG, 
+                new GrammarAction( "Store Bind Simple Authentication value" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+
+                    BindRequest bindRequestMessage = ldapMessageContainer.getLdapMessage().getBindRequest();
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    // Allocate the Authentication Object
+                    SimpleAuthentication authentication = null;
+
+                    authentication = new SimpleAuthentication();
+
+                    authentication.setParent( bindRequestMessage );
+
+                    bindRequestMessage.setAuthentication( authentication );
+
+                    // We have to handle the special case of a 0 length simple
+                    if ( tlv.getLength() == 0 )
+                    {
+                        authentication.setSimple( StringTools.EMPTY_BYTES );
+                    }
+                    else
+                    {
+                        authentication.setSimple( tlv.getValue().getData() );
+                    }
+
+                    // We can have an END transition
+                    ldapMessageContainer.grammarEndAllowed( true );
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "The simple authentication is : {}", authentication.getSimple() );
+                    }
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // ExtendedRequest Message.
+        // transition from Simple Authentication to Controls.
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... ExtendedResponse ...
-        // ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
-        // We have to switch to the ExtendedResponse grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.EXTENDED_RESPONSE_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.EXTENDED_RESPONSE_GRAMMAR_SWITCH, null );
+        //         bindRequest   BindRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.SIMPLE_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.SIMPLE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from name to SASL Authentication
+        // --------------------------------------------------------------------------------------------
+        // BindRequest ::= [APPLICATION 0] SEQUENCE {
+        //     ....
+        //     authentication          AuthenticationChoice }
+        //
+        // AuthenticationChoice ::= CHOICE {
+        //     ...
+        //     sasl                  [3] SaslCredentials }
+        //     ...
+        //
+        // We have to create an Authentication Object to store the credentials.
+        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SASL_TAG] = 
+            new GrammarTransition( LdapStatesEnum.NAME_STATE, LdapStatesEnum.SASL_STATE, LdapConstants.BIND_REQUEST_SASL_TAG, 
+                new GrammarAction( "Initialize Bind SASL Authentication" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    BindRequest bindRequestMessage = ldapMessage.getBindRequest();
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    // We will check that the sasl is not null
+                    if ( tlv.getLength() == 0 )
+                    {
+                        String msg = "The SaslCredential must not be null";
+                        log.error( msg );
+                        
+                        BindResponseImpl response = new BindResponseImpl( ldapMessage.getMessageId() );
+                    
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALIDCREDENTIALS, 
+                            bindRequestMessage.getName(), null );
+                    }
+
+                    // Create the SaslCredentials Object
+                    SaslCredentials authentication = new SaslCredentials();
+
+                    authentication.setParent( bindRequestMessage );
+
+                    bindRequestMessage.setAuthentication( authentication );
+
+                    if ( IS_DEBUG ) 
+                    {
+                        log.debug( "The SaslCredential has been created" );
+                    }
+
+                    return;
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
-        // Controls
+        // Transition from SASL Authentication to Mechanism
         // --------------------------------------------------------------------------------------------
-        // LdapMessage ::= ... extendedResp ExtendedResponse },
-        // controls [0] Controls OPTIONAL }
-        // 
-        // We have to switch to the Controls grammar
-        super.transitions[LdapStatesEnum.PROTOCOL_OP_TAG][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
-            LdapStatesEnum.PROTOCOL_OP_TAG, LdapStatesEnum.LDAP_CONTROL_GRAMMAR_SWITCH, null );
-    }
+        // SaslCredentials ::= SEQUENCE {
+        //     mechanism   LDAPSTRING,
+        //     ...
+        //
+        // We have to store the mechanism.
+        super.transitions[LdapStatesEnum.SASL_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.SASL_STATE, LdapStatesEnum.MECHANISM_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new GrammarAction( "Store SASL mechanism" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    BindRequest bindRequestMessage = ldapMessage.getBindRequest();
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
 
+                    // Get the SaslCredentials Object
+                    SaslCredentials authentication = bindRequestMessage.getSaslAuthentication();
+
+                    // We have to handle the special case of a 0 length
+                    // mechanism
+                    if ( tlv.getLength() == 0 )
+                    {
+                        authentication.setMechanism( "" );
+                    }
+                    else
+                    {
+                        authentication.setMechanism( new String( tlv.getValue().getData() ) );
+                    }
+
+                    // We can have an END transition
+                    ldapMessageContainer.grammarEndAllowed( true );
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "The mechanism is : {}", authentication.getMechanism() );
+                    }
+
+                    return;
+                }
+            } );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Mechanism to Credentials
+        // --------------------------------------------------------------------------------------------
+        // SaslCredentials ::= SEQUENCE {
+        //     ...
+        //     credentials OCTET STRING OPTIONAL }
+        //
+        // We have to store the mechanism.
+        super.transitions[LdapStatesEnum.MECHANISM_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CREDENTIALS_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new GrammarAction( "Store SASL credentials" )
+            {
+                public void action( IAsn1Container container )
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+    
+                    BindRequest bindRequestMessage = ldapMessageContainer.getLdapMessage().getBindRequest();
+    
+                    // Get the Value and store it in the BindRequest
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+    
+                    SaslCredentials credentials = bindRequestMessage.getSaslAuthentication();
+    
+                    // We have to handle the special case of a 0 length
+                    // credentials
+                    if ( tlv.getLength() == 0 )
+                    {
+                        credentials.setCredentials( StringTools.EMPTY_BYTES );
+                    }
+                    else
+                    {
+                        credentials.setCredentials( tlv.getValue().getData() );
+                    }
+    
+                    // We can have an END transition
+                    ldapMessageContainer.grammarEndAllowed( true );
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "The credentials are : {}", credentials.getCredentials() );
+                    }
+    
+                    return;
+                }
+            } );
+        
+        // --------------------------------------------------------------------------------------------
+        // transition from from Mechanism to Controls.
+        // --------------------------------------------------------------------------------------------
+        //         bindRequest   BindRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.MECHANISM_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // transition from credentials to Controls.
+        // --------------------------------------------------------------------------------------------
+        //         bindRequest   BindRequest,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from MessageId to BindResponse message 
+        // --------------------------------------------------------------------------------------------
+        // LdapMessage ::= ... BindResponse ...
+        // BindResponse ::= [APPLICATION 1] SEQUENCE { ...
+        // We have to switch to the BindResponse grammar
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_RESPONSE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_RESPONSE_STATE, LdapConstants.BIND_RESPONSE_TAG, 
+                new GrammarAction( "Init BindReponse" )
+            {
+                public void action( IAsn1Container container )
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // Now, we can allocate the BindRequest Object
+                    BindResponse bindResponse = new BindResponse();
+
+                    // As this is a new Constructed object, we have to init its
+                    // length
+                    bindResponse.setParent( ldapMessage );
+
+                    // And we associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( bindResponse );
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from BindResponse message to Result Code BR 
+        // --------------------------------------------------------------------------------------------
+        // BindResponse ::= [APPLICATION 1] SEQUENCE {
+        //     COMPONENTS OF LDAPResult,
+        //     ...
+        //
+        // LDAPResult ::= SEQUENCE {
+        //     resultCode ENUMERATED { 
+        //         ...
+        // 
+        // Stores the result code into the Bind Response object
+        super.transitions[LdapStatesEnum.BIND_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
+            new GrammarTransition( LdapStatesEnum.BIND_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_BR_STATE, UniversalTag.ENUMERATED_TAG, 
+                new ResultCodeAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Result Code BR to Matched DN BR 
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     matchedDN LDAPDN,
+        //     ...
+        //
+        // Stores the matched DN
+        super.transitions[LdapStatesEnum.RESULT_CODE_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.RESULT_CODE_BR_STATE, LdapStatesEnum.MATCHED_DN_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new MatchedDNAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Matched DN BR to Error Message BR 
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     errorMessage LDAPString,
+        //     ...
+        //
+        // Stores the error message
+        super.transitions[LdapStatesEnum.MATCHED_DN_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MATCHED_DN_BR_STATE, LdapStatesEnum.ERROR_MESSAGE_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ErrorMessageAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Error Message BR to Server SASL credentials 
+        // --------------------------------------------------------------------------------------------
+        // BindResponse ::= APPLICATION 1] SEQUENCE {
+        //     ...
+        //     serverSaslCreds [7] OCTET STRING OPTIONAL }
+        //
+        // Stores the sasl credentials 
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapConstants.SERVER_SASL_CREDENTIAL_TAG, 
+                new ServerSASLCredsAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Error Message BR to Referrals BR 
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     referral   [3] Referral OPTIONNAL }
+        //
+        // Initialiaze the referrals list 
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.REFERRALS_BR_STATE, LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, 
+                new InitReferralsAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referrals BR to Referral BR 
+        // --------------------------------------------------------------------------------------------
+        // Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI (RFC 4511)
+        // URI ::= LDAPString
+        //
+        // Add a first Referral
+        super.transitions[LdapStatesEnum.REFERRALS_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRALS_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ReferralAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referral BR to Referral BR 
+        // --------------------------------------------------------------------------------------------
+        // Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI (RFC 4511)
+        // URI ::= LDAPString
+        //
+        // Adda new Referral
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ReferralAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referral BR to Server SASL Credentials 
+        // --------------------------------------------------------------------------------------------
+        // Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI (RFC 4511)
+        // URI ::= LDAPString
+        //
+        // Adda new Referral
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapConstants.SERVER_SASL_CREDENTIAL_TAG, 
+                new ServerSASLCredsAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referral BR to Controls 
+        // --------------------------------------------------------------------------------------------
+        //         bindResponse   BindResponse,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        // Adda new Referral
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Error Message BR to controls 
+        // --------------------------------------------------------------------------------------------
+        //         bindResponse   BindResponse,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        //  
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Server SASL credentials to Controls 
+        // --------------------------------------------------------------------------------------------
+        //         bindResponse   BindResponse,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        super.transitions[LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Result Code to Matched DN 
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     matchedDN LDAPDN,
+        //     ...
+        //
+        // Stores the matched DN
+        super.transitions[LdapStatesEnum.RESULT_CODE_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.RESULT_CODE_STATE, LdapStatesEnum.MATCHED_DN_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new MatchedDNAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Matched DN to Error Message 
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     errorMessage LDAPString,
+        //     ...
+        //
+        // Stores the error message
+        super.transitions[LdapStatesEnum.MATCHED_DN_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MATCHED_DN_STATE, LdapStatesEnum.ERROR_MESSAGE_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ErrorMessageAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Error Message to Referrals
+        // --------------------------------------------------------------------------------------------
+        // LDAPResult ::= SEQUENCE {
+        //     ...
+        //     referral   [3] Referral OPTIONNAL }
+        //
+        // Initialiaze the referrals list 
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.REFERRALS_STATE, LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, 
+                new GrammarAction(
+                "Init referrals list" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    LdapResponse response = ldapMessage.getLdapResponse();
+                    LdapResult ldapResult = response.getLdapResult();
+                    
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    // If we hae a Referrals sequence, then it should not be empty
+                    // sasl credentials
+                    if ( tlv.getLength() == 0 )
+                    {
+                        String msg = "The Referrals must not be null";
+                        log.error( msg );
+                     
+                        // This will generate a PROTOCOL_ERROR
+                        throw new DecoderException( msg );
+                    }
+
+                    ldapResult.initReferrals();
+                }
+            } );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referrals to Referral 
+        // --------------------------------------------------------------------------------------------
+        // Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI (RFC 4511)
+        // URI ::= LDAPString
+        //
+        // Add a first Referral
+        super.transitions[LdapStatesEnum.REFERRALS_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRALS_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ReferralAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referral to Referral 
+        // --------------------------------------------------------------------------------------------
+        // Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI (RFC 4511)
+        // URI ::= LDAPString
+        //
+        // Adda new Referral
+        super.transitions[LdapStatesEnum.REFERRAL_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new ReferralAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Referral to Controls 
+        // --------------------------------------------------------------------------------------------
+        //         xxxResponse   xxxResponse,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        // Adda new Referral
+        super.transitions[LdapStatesEnum.REFERRAL_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
+                new ControlsInitAction() );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Error Message to controls 
+        // --------------------------------------------------------------------------------------------
+        //         xxxResponse   xxxResponse,
+        //         ... },
+        //     controls       [0] Controls OPTIONAL }
+        //
+        //  
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from MessageId to SearchResultEntry Message.
+        // --------------------------------------------------------------------------------------------
+        // LdapMessage ::= ... SearchResultEntry ...
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        //
+        // Initialize the searchResultEntry object
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_ENTRY_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE, LdapConstants.SEARCH_RESULT_ENTRY_TAG, 
+                new GrammarAction( "Init SearchResultEntry" )
+            {
+                public void action( IAsn1Container container )
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // Now, we can allocate the SearchResultEntry Object
+                    // And we associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( new SearchResultEntry() );
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from SearchResultEntry Message to ObjectName
+        // --------------------------------------------------------------------------------------------
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        // objectName LDAPDN,
+        // ...
+        //
+        // Store the object name.
+        super.transitions[LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE, LdapStatesEnum.OBJECT_NAME_STATE, UniversalTag.OCTET_STRING_TAG,
+                new GrammarAction( "Store search result entry object name Value" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    SearchResultEntry searchResultEntry = ldapMessage.getSearchResultEntry();
+
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    LdapDN objectName = LdapDN.EMPTY_LDAPDN;
+
+                    // Store the value.
+                    if ( tlv.getLength() == 0 )
+                    {
+                        searchResultEntry.setObjectName( objectName );
+                    }
+                    else
+                    {
+                        byte[] dnBytes = tlv.getValue().getData();
+
+                        try
+                        {
+                            objectName = new LdapDN( dnBytes );
+                        }
+                        catch ( InvalidNameException ine )
+                        {
+                            // This is for the client side. We will never decode LdapResult on the server
+                            String msg = "The DN " + StringTools.dumpBytes( dnBytes )
+                                + "is invalid : " + ine.getMessage();
+                            log.error( "{} : {}", msg, ine.getMessage() );
+                            throw new DecoderException( msg, ine );
+                        }
+
+                        searchResultEntry.setObjectName( objectName );
+                    }
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "Search Result Entry DN found : {}", searchResultEntry.getObjectName() );
+                    }
+                }
+            } );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from ObjectName to AttributesSR
+        // --------------------------------------------------------------------------------------------
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        // ...
+        // attributes PartialAttributeList }
+        //
+        // PartialAttributeList ::= *SEQUENCE* OF SEQUENCE {
+        // ...
+        //
+        // We may have no attributes. Just allows the grammar to end
+        super.transitions[LdapStatesEnum.OBJECT_NAME_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.OBJECT_NAME_STATE, LdapStatesEnum.ATTRIBUTES_SR_STATE, UniversalTag.SEQUENCE_TAG,
+                new GrammarAction( "Pop and end allowed" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    container.grammarEndAllowed( true );
+                }
+            } );               
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from AttributesSR to PartialAttributesList
+        // --------------------------------------------------------------------------------------------
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        // ...
+        // attributes PartialAttributeList }
+        //
+        // PartialAttributeList ::= SEQUENCE OF *SEQUENCE* {
+        // ...
+        //
+        // nothing to do
+        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from AttributesSR to Controls
+        // --------------------------------------------------------------------------------------------
+        //     searchResultEntry SearchResultEntry,
+        //     ... },
+        // controls   [0] Controls OPTIONAL }
+        //
+        // Initialize the controls
+        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from PartialAttributesList to typeSR
+        // --------------------------------------------------------------------------------------------
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        // ...
+        // attributes PartialAttributeList }
+        //
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     type  AttributeDescription,
+        //     ...
+        //
+        // Store the attribute's name.
+        super.transitions[LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, LdapStatesEnum.TYPE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new GrammarAction( "Store search result entry object name Value" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    SearchResultEntry searchResultEntry = ldapMessage.getSearchResultEntry();
+
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    String type = "";
+
+                    // Store the name
+                    if ( tlv.getLength() == 0 )
+                    {
+                        searchResultEntry.addAttributeValues( type );
+                    }
+                    else
+                    {
+                        type = new String( tlv.getValue().getData() );
+                        searchResultEntry.addAttributeValues( type );
+                    }
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "Attribute type : {}", type );
+                    }
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from typeSR to ValsSR
+        // --------------------------------------------------------------------------------------------
+        // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
+        // ...
+        // attributes PartialAttributeList }
+        //
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     ...
+        //     vals SET OF AttributeValue }
+        //
+        // We may have no value. Just allows the grammar to end
+        super.transitions[LdapStatesEnum.TYPE_SR_STATE][UniversalTag.SET_TAG] = 
+            new GrammarTransition( LdapStatesEnum.TYPE_SR_STATE, LdapStatesEnum.VALS_SR_STATE, UniversalTag.SET_TAG, 
+                new GrammarAction( "Grammar end allowed" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+                    container.grammarEndAllowed( true );
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from ValsSR to AttributeValueSR
+        // --------------------------------------------------------------------------------------------
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     ...
+        //     vals SET OF AttributeValue }
+        //
+        // AttributeValue ::= OCTET STRING
+        // 
+        // Store the attribute value
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new SearchResultAttributeValueAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from ValsSR to PartialAttributesList
+        // --------------------------------------------------------------------------------------------
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     ...
+        //     vals SET OF AttributeValue }
+        // 
+        // Loop when we don't have any attribute value. Nothing to do
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from ValsSR to Controls
+        // --------------------------------------------------------------------------------------------
+        //     searchResultEntry SearchResultEntry,
+        //     ... },
+        // controls   [0] Controls OPTIONAL }
+        //
+        // Initialize the controls
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from AttributeValueSR to AttributeValueSR 
+        // --------------------------------------------------------------------------------------------
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     ...
+        //     vals SET OF AttributeValue }
+        //
+        // AttributeValue ::= OCTET STRING
+        // 
+        // Store the attribute value
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new SearchResultAttributeValueAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from AttributeValueSR to PartialAttributesList
+        // --------------------------------------------------------------------------------------------
+        // PartialAttributeList ::= SEQUENCE OF SEQUENCE {
+        //     ...
+        //     vals SET OF AttributeValue }
+        // 
+        // Loop when we don't have any attribute value. Nothing to do
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from AttributeValueSR to Controls
+        // --------------------------------------------------------------------------------------------
+        //     searchResultEntry SearchResultEntry,
+        //     ... },
+        // controls   [0] Controls OPTIONAL }
+        //
+        // Initialize the controls
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][LdapConstants.CONTROLS_TAG] = 
+            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+                new ControlsInitAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // SearchResultDone Message.
+        // --------------------------------------------------------------------------------------------
+        // LdapMessage ::= ... SearchResultDone ...
+        // SearchResultDone ::= [APPLICATION 5] SEQUENCE { ...
+        // 
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_DONE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_DONE_STATE, LdapConstants.SEARCH_RESULT_DONE_TAG, 
+                new GrammarAction( "Init search Result Done" )
+            {
+                public void action( IAsn1Container container )
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // Now, we can allocate the SearchResultDone Object
+                    ldapMessage.setProtocolOP( new SearchResultDone() );
+
+                    log.debug( "Search Result Done found" );
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // SearchResultDone Message.
+        // --------------------------------------------------------------------------------------------
+        // LdapMessage ::= ... SearchResultDone ...
+        // SearchResultDone ::= [APPLICATION 5] LDAPResult
+        //
+        // LDAPResult ::= SEQUENCE {
+        //     resultCode    ENUMERATED {
+        //         ...
+        // 
+        // Stores the result code
+        super.transitions[LdapStatesEnum.SEARCH_RESULT_DONE_STATE][UniversalTag.ENUMERATED_TAG] = 
+            new GrammarTransition( LdapStatesEnum.SEARCH_RESULT_DONE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
+                new ResultCodeAction() );
+        
+        // --------------------------------------------------------------------------------------------
+        // Transition from Message ID to ModifyRequest Message
+        // --------------------------------------------------------------------------------------------
+        // LdapMessage ::= ... ModifyRequest ...
+        // ModifyRequest ::= [APPLICATION 6] SEQUENCE { ...
+        //
+        // Creates the Modify Request object
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_REQUEST_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_REQUEST_STATE, LdapConstants.MODIFY_REQUEST_TAG, 
+                new GrammarAction( "Init ModifyRequest" )
+            {
+                public void action( IAsn1Container container )
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+
+                    // Now, we can allocate the ModifyRequest Object
+                    // And we associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( new ModifyRequest() );
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from ModifyRequest Message to Object
+        // --------------------------------------------------------------------------------------------
+        // ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+        //     object    LDAPDN,
+        //     ...
+        //
+        // Stores the object DN
+        super.transitions[LdapStatesEnum.MODIFY_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
+            new GrammarTransition( LdapStatesEnum.MODIFY_REQUEST_STATE, LdapStatesEnum.OBJECT_STATE, UniversalTag.OCTET_STRING_TAG, 
+                new GrammarAction( "Store Modify request object Value" )
+            {
+                public void action( IAsn1Container container ) throws DecoderException
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    ModifyRequest modifyRequest = ldapMessage.getModifyRequest();
+
+                    TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+                    LdapDN object = LdapDN.EMPTY_LDAPDN;
+
+                    // Store the value.
+                    if ( tlv.getLength() == 0 )
+                    {
+                        modifyRequest.setObject( object );
+                    }
+                    else
+                    {
+                        byte[] dnBytes = tlv.getValue().getData();
+
+                        try
+                        {
+                            object = new LdapDN( dnBytes );
+                        }
+                        catch ( InvalidNameException ine )
+                        {
+                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + 
+                                " (" + StringTools.dumpBytes( dnBytes ) + 
+                                ") is invalid";
+                            log.error( "{} : {}", msg, ine.getMessage() );
+                    
+                            ModifyResponseImpl response = new ModifyResponseImpl( ldapMessage.getMessageId() );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALIDDNSYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                        }
+
+                        modifyRequest.setObject( object );
+                    }
+
+                    if ( IS_DEBUG )
+                    {
+                        log.debug( "Modification of DN {}", modifyRequest.getObject() );
+                    }
+                }
+            } );
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from Object to modifications
+        // --------------------------------------------------------------------------------------------
+        // ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+        //     ...
+        //     modification *SEQUENCE OF* SEQUENCE {
+        //     ...
+        //
+        // Initialize the modifications list
+        super.transitions[LdapStatesEnum.OBJECT_STATE][UniversalTag.SEQUENCE_TAG] = 
+            new GrammarTransition( LdapStatesEnum.OBJECT_STATE, LdapStatesEnum.MODIFICATIONS_STATE, UniversalTag.SEQUENCE_TAG, 
+                new GrammarAction( "Init modifications array list" )
+            {
+                public void action( IAsn1Container container )
+                {
+
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    ModifyRequest modifyRequest = ldapMessage.getModifyRequest();
+
+                    modifyRequest.initModifications();
+                }
+            } );                
+
+        // --------------------------------------------------------------------------------------------
+        // Transition from modifications to modification sequence

[... 4973 lines stripped ...]