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   *    http://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  
21  package org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure;
22  
23  
24  import org.apache.directory.api.asn1.DecoderException;
25  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
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.TLV;
29  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
30  import org.apache.directory.api.i18n.I18n;
31  import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
32  import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureParameter;
33  import org.apache.directory.api.util.Strings;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  
38  /**
39   * ASN.1 BER Grammar for Stored Procedure Extended Operation
40   * 
41   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
42   */
43  public final class StoredProcedureGrammar extends AbstractGrammar<StoredProcedureContainer>
44  {
45      //~ Static fields/initializers -----------------------------------------------------------------
46  
47      /** The logger */
48      //private static final Logger log = LoggerFactory.getLogger( StoredProcedureGrammar.class );
49      static final Logger LOG = LoggerFactory.getLogger( StoredProcedureGrammar.class );
50  
51      /** The instance of grammar. StoredProcedureGrammar is a singleton. */
52      private static StoredProcedureGrammar instance = new StoredProcedureGrammar();
53  
54  
55      //~ Constructors -------------------------------------------------------------------------------
56  
57      /**
58       * Creates a new StoredProcedureGrammar object.
59       */
60      @SuppressWarnings("unchecked")
61      private StoredProcedureGrammar()
62      {
63          setName( StoredProcedureGrammar.class.getName() );
64  
65          // Create the transitions table
66          super.transitions = new GrammarTransition[StoredProcedureStatesEnum.LAST_STORED_PROCEDURE_STATE.ordinal()][256];
67  
68          //============================================================================================
69          // StoredProcedure Message
70          //============================================================================================
71          // StoredProcedure ::= SEQUENCE {
72          //   ...
73          // Nothing to do.
74          super.transitions[StoredProcedureStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
75              new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.START_STATE,
76                  StoredProcedureStatesEnum.STORED_PROCEDURE_STATE,
77                  UniversalTag.SEQUENCE.getValue(),
78                  null );
79  
80          //    language OCTETSTRING, (Tag)
81          //    ...
82          //
83          // Creates the storeProcedure and stores the language
84          super.transitions[StoredProcedureStatesEnum.STORED_PROCEDURE_STATE.ordinal()][UniversalTag.OCTET_STRING
85              .getValue()] =
86              new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.STORED_PROCEDURE_STATE,
87                  StoredProcedureStatesEnum.LANGUAGE_STATE,
88                  UniversalTag.OCTET_STRING.getValue(),
89                  new GrammarAction<StoredProcedureContainer>( "Stores the language" )
90                  {
91                      public void action( StoredProcedureContainer container ) throws DecoderException
92                      {
93                          TLV tlv = container.getCurrentTLV();
94  
95                          StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure();
96                          if ( storedProcedure == null )
97                          {
98                              storedProcedure = new StoredProcedureRequestDecorator( LdapApiServiceFactory.getSingleton() );
99                              container.setStoredProcedure( storedProcedure );
100                         }
101 
102                         // Store the value.
103                         if ( tlv.getLength() == 0 )
104                         {
105                             // We can't have a void language !
106                             String msg = I18n.err( I18n.ERR_04038 );
107                             LOG.error( msg );
108                             throw new DecoderException( msg );
109                         }
110                         else
111                         {
112                             // Only this field's type is String by default
113                             String language = Strings.utf8ToString( tlv.getValue().getData() );
114 
115                             if ( LOG.isDebugEnabled() )
116                             {
117                                 LOG.debug( "SP language found: " + language );
118                             }
119 
120                             storedProcedure.setLanguage( language );
121                         }
122                     }
123                 } );
124 
125         //    procedure OCTETSTRING, (Value)
126         //    ...
127         // Stores the procedure.
128         super.transitions[StoredProcedureStatesEnum.LANGUAGE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
129             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.LANGUAGE_STATE,
130                 StoredProcedureStatesEnum.PROCEDURE_STATE,
131                 UniversalTag.OCTET_STRING.getValue(),
132                 new GrammarAction<StoredProcedureContainer>( "Stores the procedure" )
133                 {
134                     public void action( StoredProcedureContainer container ) throws DecoderException
135                     {
136                         TLV tlv = container.getCurrentTLV();
137 
138                         StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure();
139 
140                         // Store the value.
141                         if ( tlv.getLength() == 0 )
142                         {
143                             // We can't have a void procedure !
144                             String msg = I18n.err( I18n.ERR_04039 );
145                             LOG.error( msg );
146                             throw new DecoderException( msg );
147                         }
148                         else
149                         {
150                             byte[] procedure = tlv.getValue().getData();
151 
152                             storedProcedure.setProcedure( procedure );
153                         }
154 
155                         if ( LOG.isDebugEnabled() )
156                         {
157                             LOG.debug( "Procedure found : " + storedProcedure.getProcedureSpecification() );
158                         }
159                     }
160                 } );
161 
162         // parameters SEQUENCE OF Parameter { (Value)
163         //    ...
164         // The list of parameters will be created with the first parameter.
165         // We can have an empty list of parameters, so the PDU can be empty
166         super.transitions[StoredProcedureStatesEnum.PROCEDURE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
167             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PROCEDURE_STATE,
168                 StoredProcedureStatesEnum.PARAMETERS_STATE,
169                 UniversalTag.SEQUENCE.getValue(),
170                 new GrammarAction<StoredProcedureContainer>( "Stores the parameters" )
171                 {
172                     public void action( StoredProcedureContainer container ) throws DecoderException
173                     {
174                         container.setGrammarEndAllowed( true );
175                     }
176                 } );
177 
178         // parameter SEQUENCE OF { (Value)
179         //    ...
180         // Nothing to do. 
181         super.transitions[StoredProcedureStatesEnum.PARAMETERS_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
182             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETERS_STATE,
183                 StoredProcedureStatesEnum.PARAMETER_STATE,
184                 UniversalTag.SEQUENCE.getValue(),
185                 null );
186 
187         // Parameter ::= {
188         //    type OCTETSTRING, (Value)
189         //    ...
190         //
191         // We can create a parameter, and store its type
192         super.transitions[StoredProcedureStatesEnum.PARAMETER_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
193             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_STATE,
194                 StoredProcedureStatesEnum.PARAMETER_TYPE_STATE,
195                 UniversalTag.OCTET_STRING.getValue(),
196                 new GrammarAction<StoredProcedureContainer>( "Store parameter type" )
197                 {
198                     public void action( StoredProcedureContainer container ) throws DecoderException
199                     {
200                         TLV tlv = container.getCurrentTLV();
201                         StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure();
202 
203                         // Store the value.
204                         if ( tlv.getLength() == 0 )
205                         {
206                             // We can't have a void parameter type !
207                             String msg = I18n.err( I18n.ERR_04040 );
208                             LOG.error( msg );
209                             throw new DecoderException( msg );
210                         }
211                         else
212                         {
213                             StoredProcedureParameter parameter = new StoredProcedureParameter();
214 
215                             byte[] parameterType = tlv.getValue().getData();
216 
217                             parameter.setType( parameterType );
218 
219                             // We store the type in the current parameter.
220                             storedProcedure.setCurrentParameter( parameter );
221 
222                             if ( LOG.isDebugEnabled() )
223                             {
224                                 LOG.debug( "Parameter type found : " + Strings.dumpBytes( parameterType ) );
225                             }
226 
227                         }
228                     }
229                 } );
230 
231         // Parameter ::= {
232         //    ...
233         //    value OCTETSTRING (Tag)
234         // }
235         // Store the parameter value
236         super.transitions[StoredProcedureStatesEnum.PARAMETER_TYPE_STATE.ordinal()][UniversalTag.OCTET_STRING
237             .getValue()] =
238             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_TYPE_STATE,
239                 StoredProcedureStatesEnum.PARAMETER_VALUE_STATE,
240                 UniversalTag.OCTET_STRING.getValue(),
241                 new GrammarAction<StoredProcedureContainer>( "Store parameter value" )
242                 {
243                     public void action( StoredProcedureContainer container ) throws DecoderException
244                     {
245                         StoredProcedureContainer storedProcedureContainer = container;
246 
247                         TLV tlv = storedProcedureContainer.getCurrentTLV();
248                         StoredProcedureRequestDecorator storedProcedure = storedProcedureContainer.getStoredProcedure();
249 
250                         // Store the value.
251                         if ( tlv.getLength() == 0 )
252                         {
253                             // We can't have a void parameter value !
254                             String msg = I18n.err( I18n.ERR_04041 );
255                             LOG.error( msg );
256                             throw new DecoderException( msg );
257                         }
258                         else
259                         {
260                             byte[] parameterValue = tlv.getValue().getData();
261 
262                             if ( parameterValue.length != 0 )
263                             {
264                                 StoredProcedureParameter parameter = storedProcedure.getCurrentParameter();
265                                 parameter.setValue( parameterValue );
266 
267                                 // We can now add a new Parameter to the procedure
268                                 storedProcedure.addParameter( parameter );
269 
270                                 if ( LOG.isDebugEnabled() )
271                                 {
272                                     LOG.debug( "Parameter value found : " + Strings.dumpBytes( parameterValue ) );
273                                 }
274                             }
275                             else
276                             {
277                                 String msg = I18n.err( I18n.ERR_04042 );
278                                 LOG.error( msg );
279                                 throw new DecoderException( msg );
280                             }
281                         }
282 
283                         // The only possible END state for the grammar is here
284                         container.setGrammarEndAllowed( true );
285                     }
286                 } );
287 
288         // Parameters ::= SEQUENCE OF Parameter
289         // 
290         // Loop on next parameter
291         super.transitions[StoredProcedureStatesEnum.PARAMETER_VALUE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
292             new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_VALUE_STATE,
293                 StoredProcedureStatesEnum.PARAMETER_STATE,
294                 UniversalTag.SEQUENCE.getValue(),
295                 null );
296     }
297 
298 
299     //~ Methods ------------------------------------------------------------------------------------
300 
301     /**
302      * Get the instance of this grammar
303      *
304      * @return An instance on the StoredProcedure Grammar
305      */
306     public static StoredProcedureGrammar getInstance()
307     {
308         return instance;
309     }
310 }