001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020
021 package org.apache.directory.shared.ldap.codec.extended.operations.storedProcedure;
022
023
024 import org.apache.directory.shared.asn1.ber.IAsn1Container;
025 import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
026 import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
027 import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
028 import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
029 import org.apache.directory.shared.asn1.ber.tlv.TLV;
030 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
031 import org.apache.directory.shared.asn1.codec.DecoderException;
032 import org.apache.directory.shared.ldap.codec.extended.operations.storedProcedure.StoredProcedure.StoredProcedureParameter;
033 import org.apache.directory.shared.ldap.util.StringTools;
034 import org.slf4j.Logger;
035 import org.slf4j.LoggerFactory;
036
037
038 /**
039 * ASN.1 BER Grammar for Stored Procedure Extended Operation
040 *
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 * @version $Rev$, $Date$,
043 */
044 public class StoredProcedureGrammar extends AbstractGrammar
045 {
046 //~ Static fields/initializers -----------------------------------------------------------------
047
048 /** The logger */
049 //private static final Logger log = LoggerFactory.getLogger( StoredProcedureGrammar.class );
050 static final Logger log = LoggerFactory.getLogger( StoredProcedureGrammar.class );
051
052 /** The instance of grammar. StoredProcedureGrammar is a singleton. */
053 private static IGrammar instance = new StoredProcedureGrammar();
054
055
056 //~ Constructors -------------------------------------------------------------------------------
057
058 /**
059 * Creates a new StoredProcedureGrammar object.
060 */
061 private StoredProcedureGrammar()
062 {
063 name = StoredProcedureGrammar.class.getName();
064 statesEnum = StoredProcedureStatesEnum.getInstance();
065
066 // Create the transitions table
067 super.transitions = new GrammarTransition[StoredProcedureStatesEnum.LAST_STORED_PROCEDURE_STATE][256];
068
069 //============================================================================================
070 // StoredProcedure Message
071 //============================================================================================
072 // StoredProcedure ::= SEQUENCE {
073 // ...
074 // Nothing to do.
075 super.transitions[StoredProcedureStatesEnum.START_STATE][UniversalTag.SEQUENCE_TAG] =
076 new GrammarTransition( StoredProcedureStatesEnum.START_STATE,
077 StoredProcedureStatesEnum.STORED_PROCEDURE_STATE,
078 UniversalTag.SEQUENCE_TAG,
079 null );
080
081 // language OCTETSTRING, (Tag)
082 // ...
083 //
084 // Creates the storeProcedure and stores the language
085 super.transitions[StoredProcedureStatesEnum.STORED_PROCEDURE_STATE][UniversalTag.OCTET_STRING_TAG] =
086 new GrammarTransition( StoredProcedureStatesEnum.STORED_PROCEDURE_STATE,
087 StoredProcedureStatesEnum.LANGUAGE_STATE,
088 UniversalTag.OCTET_STRING_TAG,
089 new GrammarAction( "Stores the language" )
090 {
091 public void action( IAsn1Container container ) throws DecoderException
092 {
093
094 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container;
095
096 TLV tlv = storedProcedureContainer.getCurrentTLV();
097
098 StoredProcedure storedProcedure = null;
099
100 // Store the value.
101 if ( tlv.getLength() == 0 )
102 {
103 // We can't have a void language !
104 log.error( "The stored procedure language is null" );
105 throw new DecoderException( "The stored procedure language cannot be null" );
106 }
107 else
108 {
109 // Only this field's type is String by default
110 String language = StringTools.utf8ToString( tlv.getValue().getData() );
111
112 if ( log.isDebugEnabled() )
113 {
114 log.debug( "SP language found: " + language );
115 }
116
117 storedProcedure = new StoredProcedure();
118 storedProcedure.setLanguage( language );
119 storedProcedureContainer.setStoredProcedure( storedProcedure );
120 }
121 }
122 } );
123
124 // procedure OCTETSTRING, (Value)
125 // ...
126 // Stores the procedure.
127 super.transitions[StoredProcedureStatesEnum.LANGUAGE_STATE][UniversalTag.OCTET_STRING_TAG] =
128 new GrammarTransition( StoredProcedureStatesEnum.LANGUAGE_STATE,
129 StoredProcedureStatesEnum.PROCEDURE_STATE,
130 UniversalTag.OCTET_STRING_TAG,
131 new GrammarAction(
132 "Stores the procedure" )
133 {
134 public void action( IAsn1Container container ) throws DecoderException
135 {
136
137 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container;
138
139 TLV tlv = storedProcedureContainer.getCurrentTLV();
140
141 StoredProcedure storedProcedure = storedProcedureContainer.getStoredProcedure();
142
143 // Store the value.
144 if ( tlv.getLength() == 0 )
145 {
146 // We can't have a void procedure !
147 log.error( "The procedure can't be null" );
148 throw new DecoderException( "The procedure can't be null" );
149 }
150 else
151 {
152 byte[] procedure = tlv.getValue().getData();
153
154 storedProcedure.setProcedure( procedure );
155 }
156
157 if ( log.isDebugEnabled() )
158 {
159 log.debug( "Procedure found : " + StringTools.utf8ToString( storedProcedure.getProcedure() ) );
160 }
161 }
162 } );
163
164 // parameters SEQUENCE OF Parameter { (Value)
165 // ...
166 // The list of parameters will be created with the first parameter.
167 // We can have an empty list of parameters, so the PDU can be empty
168 super.transitions[StoredProcedureStatesEnum.PROCEDURE_STATE][UniversalTag.SEQUENCE_TAG] =
169 new GrammarTransition( StoredProcedureStatesEnum.PROCEDURE_STATE,
170 StoredProcedureStatesEnum.PARAMETERS_STATE,
171 UniversalTag.SEQUENCE_TAG,
172 new GrammarAction(
173 "Stores the parameters" )
174 {
175 public void action( IAsn1Container container ) throws DecoderException
176 {
177 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container;
178 storedProcedureContainer.grammarEndAllowed( true );
179 }
180 } );
181
182 // parameter SEQUENCE OF { (Value)
183 // ...
184 // Nothing to do.
185 super.transitions[StoredProcedureStatesEnum.PARAMETERS_STATE][UniversalTag.SEQUENCE_TAG] =
186 new GrammarTransition( StoredProcedureStatesEnum.PARAMETERS_STATE,
187 StoredProcedureStatesEnum.PARAMETER_STATE,
188 UniversalTag.SEQUENCE_TAG,
189 null );
190
191 // Parameter ::= {
192 // type OCTETSTRING, (Value)
193 // ...
194 //
195 // We can create a parameter, and store its type
196 super.transitions[StoredProcedureStatesEnum.PARAMETER_STATE][UniversalTag.OCTET_STRING_TAG] =
197 new GrammarTransition( StoredProcedureStatesEnum.PARAMETER_STATE,
198 StoredProcedureStatesEnum.PARAMETER_TYPE_STATE,
199 UniversalTag.OCTET_STRING_TAG,
200 new GrammarAction( "Store parameter type" )
201 {
202 public void action( IAsn1Container container ) throws DecoderException
203 {
204 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container;
205
206 TLV tlv = storedProcedureContainer.getCurrentTLV();
207 StoredProcedure storedProcedure = storedProcedureContainer.getStoredProcedure();
208
209 // Store the value.
210 if ( tlv.getLength() == 0 )
211 {
212 // We can't have a void parameter type !
213 log.error( "The parameter type can't be null" );
214 throw new DecoderException( "The parameter type can't be null" );
215 }
216 else
217 {
218 StoredProcedureParameter parameter = new StoredProcedureParameter();
219
220 byte[] parameterType = tlv.getValue().getData();
221
222 parameter.setType( parameterType );
223
224 // We store the type in the current parameter.
225 storedProcedure.setCurrentParameter( parameter );
226
227 if ( log.isDebugEnabled() )
228 {
229 log.debug( "Parameter type found : " + StringTools.dumpBytes( parameterType ) );
230 }
231
232 }
233 }
234 } );
235
236 // Parameter ::= {
237 // ...
238 // value OCTETSTRING (Tag)
239 // }
240 // Store the parameter value
241 super.transitions[StoredProcedureStatesEnum.PARAMETER_TYPE_STATE][UniversalTag.OCTET_STRING_TAG] =
242 new GrammarTransition( StoredProcedureStatesEnum.PARAMETER_TYPE_STATE,
243 StoredProcedureStatesEnum.PARAMETER_VALUE_STATE,
244 UniversalTag.OCTET_STRING_TAG,
245 new GrammarAction( "Store parameter value" )
246 {
247 public void action( IAsn1Container container ) throws DecoderException
248 {
249 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container;
250
251 TLV tlv = storedProcedureContainer.getCurrentTLV();
252 StoredProcedure storedProcedure = storedProcedureContainer.getStoredProcedure();
253
254 // Store the value.
255 if ( tlv.getLength() == 0 )
256 {
257 // We can't have a void parameter value !
258 log.error( "The parameter value can't be null" );
259 throw new DecoderException( "The parameter value can't be null" );
260 }
261 else
262 {
263 byte[] parameterValue = tlv.getValue().getData();
264
265 if ( parameterValue.length != 0 )
266 {
267 StoredProcedureParameter parameter = storedProcedure.getCurrentParameter();
268 parameter.setValue( parameterValue );
269
270 // We can now add a new Parameter to the procedure
271 storedProcedure.addParameter( parameter );
272
273 if ( log.isDebugEnabled() )
274 {
275 log.debug( "Parameter value found : " + StringTools.dumpBytes( parameterValue ) );
276 }
277 }
278 else
279 {
280 log.error( "The parameter value is empty. This is not allowed." );
281 throw new DecoderException( "The parameter value is empty. This is not allowed." );
282 }
283 }
284
285 // The only possible END state for the grammar is here
286 container.grammarEndAllowed( true );
287 }
288 } );
289
290 // Parameters ::= SEQUENCE OF Parameter
291 //
292 // Loop on next parameter
293 super.transitions[StoredProcedureStatesEnum.PARAMETER_VALUE_STATE][UniversalTag.SEQUENCE_TAG] =
294 new GrammarTransition( StoredProcedureStatesEnum.PARAMETER_VALUE_STATE,
295 StoredProcedureStatesEnum.PARAMETER_STATE,
296 UniversalTag.SEQUENCE_TAG,
297 null );
298 }
299
300
301 //~ Methods ------------------------------------------------------------------------------------
302
303 /**
304 * Get the instance of this grammar
305 *
306 * @return An instance on the StoredProcedure Grammar
307 */
308 public static IGrammar getInstance()
309 {
310 return instance;
311 }
312 }