View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
25  import org.apache.directory.api.asn1.ber.grammar.Grammar;
26  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
30  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
31  import org.apache.directory.api.i18n.I18n;
32  import org.apache.directory.api.util.Strings;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.BOOLEAN;
37  import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.OCTET_STRING;
38  import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.SEQUENCE;
39  
40  /**
41   * This class implements the EndTransactionRequest extended operation's ASN.1 grammar. 
42   * All the actions are declared in this class. As it is a singleton, 
43   * these declaration are only done once. The grammar is :
44   * 
45   * <pre>
46   * txnEndReq ::= SEQUENCE {
47   *         commit         BOOLEAN DEFAULT TRUE,
48   *         identifier     OCTET STRING }
49   * </pre>
50   * 
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  
54  public class EndTransactionRequestGrammar extends AbstractGrammar<EndTransactionRequestContainer>
55  {
56  
57      /** logger */
58      private static final Logger LOG = LoggerFactory.getLogger( EndTransactionRequestGrammar.class );
59  
60      /** The instance of grammar. EndTransactionRequestGrammar is a singleton */
61      private static Grammar<EndTransactionRequestContainer> instance = new EndTransactionRequestGrammar();
62  
63  
64      /**
65       * Creates a new EndTransactionRequestGrammar object.
66       */
67      @SuppressWarnings("unchecked")
68      public EndTransactionRequestGrammar()
69      {
70          setName( EndTransactionRequestGrammar.class.getName() );
71  
72          // Create the transitions table
73          super.transitions = new GrammarTransition[EndTransactionRequestStates.LAST_STATE
74              .ordinal()][256];
75  
76          /**
77           * Transition from init state to EndTransactionRequest Sequence
78           * 
79           *  txnEndReq ::= SEQUENCE {
80           *     ...
81           *     
82           * Creates the EndTransactionRequest object
83           */
84          super.transitions[EndTransactionRequestStates.START_STATE.ordinal()][SEQUENCE.getValue()] =
85              new GrammarTransition<EndTransactionRequestContainer>(
86                  EndTransactionRequestStates.START_STATE,
87                  EndTransactionRequestStates.SEQUENCE_STATE,
88                  SEQUENCE, 
89                  null );
90  
91          /**
92           * Transition from Sequence to commit flag
93           *
94           * txnEndReq ::= SEQUENCE {
95           *         commit         BOOLEAN DEFAULT TRUE,
96           *     ...
97           *     
98           * Set the commit flag into the EndTransactionRequest instance.
99           */
100         super.transitions[EndTransactionRequestStates.SEQUENCE_STATE.ordinal()][BOOLEAN.getValue()] =
101             new GrammarTransition<EndTransactionRequestContainer>(
102                 EndTransactionRequestStates.SEQUENCE_STATE,
103                 EndTransactionRequestStates.COMMIT_STATE,
104                 BOOLEAN,
105                 new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest commit flag" )
106                 {
107                     public void action( EndTransactionRequestContainer container ) throws DecoderException
108                     {
109                         BerValue value = container.getCurrentTLV().getValue();
110 
111                         try
112                         {
113                             container.getEndTransactionRequest().setCommit( BooleanDecoder.parse( value ) );
114                         }
115                         catch ( BooleanDecoderException bde )
116                         {
117                             LOG.error( I18n
118                                 .err( I18n.ERR_08221_BAD_END_TRANSACTION_COMMIT, Strings.dumpBytes( value.getData() ), bde.getMessage() ) );
119 
120                             // This will generate a PROTOCOL_ERROR
121                             throw new DecoderException( bde.getMessage(), bde );
122                         }
123                     }
124                 } );
125 
126         /**
127          * Transition from Sequence to identifier
128          *
129          * txnEndReq ::= SEQUENCE {
130          *         identifier     OCTET STRING }
131          *     
132          * Set the commit flag into the EndTransactionRequest instance.
133          */
134         super.transitions[EndTransactionRequestStates.SEQUENCE_STATE.ordinal()][OCTET_STRING.getValue()] =
135             new GrammarTransition<EndTransactionRequestContainer>(
136                 EndTransactionRequestStates.SEQUENCE_STATE,
137                 EndTransactionRequestStates.IDENTFIER_STATE,
138                 OCTET_STRING,
139                 new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest identifier" )
140                 {
141                     public void action( EndTransactionRequestContainer container )
142                     {
143                         BerValue value = container.getCurrentTLV().getValue();
144 
145                         byte[] identifier = value.getData();
146 
147                         if ( LOG.isDebugEnabled() )
148                         {
149                             LOG.debug( I18n.msg( I18n.MSG_08206_IDENTIFIER, Strings.dumpBytes( identifier ) ) );
150                         }
151 
152                         if ( identifier == null )
153                         {
154                             identifier = Strings.EMPTY_BYTES;
155                         }
156 
157                         container.getEndTransactionRequest().setTransactionId( identifier );
158 
159                         // We may have nothing left
160                         container.setGrammarEndAllowed( true );
161                     }
162                 } );
163 
164         /**
165          * Transition from commit flag to identifier
166          *
167          * txnEndReq ::= SEQUENCE {
168          *         commit         BOOLEAN DEFAULT TRUE,
169          *         identifier     OCTET STRING }
170          *     
171          * Set the identifier into the EndTransactionRequest instance.
172          */
173         super.transitions[EndTransactionRequestStates.COMMIT_STATE.ordinal()][OCTET_STRING.getValue()] =
174             new GrammarTransition<EndTransactionRequestContainer>(
175                 EndTransactionRequestStates.COMMIT_STATE,
176                 EndTransactionRequestStates.IDENTFIER_STATE,
177                 OCTET_STRING,
178                 new GrammarAction<EndTransactionRequestContainer>( "Set EndTransactionRequest identifier" )
179                 {
180                     public void action( EndTransactionRequestContainer container )
181                     {
182                         BerValue value = container.getCurrentTLV().getValue();
183 
184                         byte[] identifier = value.getData();
185 
186                         if ( LOG.isDebugEnabled() )
187                         {
188                             LOG.debug( I18n.msg( I18n.MSG_08206_IDENTIFIER, Strings.dumpBytes( identifier ) ) );
189                         }
190 
191                         if ( identifier == null )
192                         {
193                             identifier = Strings.EMPTY_BYTES;
194                         }
195 
196                         container.getEndTransactionRequest().setTransactionId( identifier );
197 
198                         // We may have nothing left
199                         container.setGrammarEndAllowed( true );
200                     }
201                 } );
202     }
203 
204 
205     /**
206      * This class is a singleton.
207      * 
208      * @return An instance on this grammar
209      */
210     public static Grammar<EndTransactionRequestContainer> getInstance()
211     {
212         return instance;
213     }
214 }