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