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 java.nio.BufferOverflowException;
025 import java.nio.ByteBuffer;
026 import java.util.ArrayList;
027 import java.util.LinkedList;
028 import java.util.List;
029
030 import org.apache.directory.shared.asn1.AbstractAsn1Object;
031 import org.apache.directory.shared.asn1.ber.tlv.TLV;
032 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
033 import org.apache.directory.shared.asn1.ber.tlv.Value;
034 import org.apache.directory.shared.asn1.codec.EncoderException;
035 import org.apache.directory.shared.ldap.util.StringTools;
036
037
038 /**
039 * Stored Procedure Extended Operation bean
040 *
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 * @version $Rev$, $Date$,
043 */
044 public class StoredProcedure extends AbstractAsn1Object
045 {
046 private String language;
047
048 private byte[] procedure;
049
050 private List<StoredProcedureParameter> parameters = new ArrayList<StoredProcedureParameter>();
051
052 private StoredProcedureParameter currentParameter;
053
054 /** The stored procedure length */
055 private int storedProcedureLength;
056
057 /** The parameters length */
058 private int parametersLength;
059
060 /** The list of all parameter lengths */
061 private List<Integer> parameterLength;
062
063 /** The list of all parameter type lengths */
064 private List<Integer> paramTypeLength;
065
066 /** The list of all parameter value lengths */
067 private List<Integer> paramValueLength;
068
069 public String getLanguage()
070 {
071 return language;
072 }
073
074
075 public void setLanguage( String language )
076 {
077 this.language = language;
078 }
079
080
081 public byte[] getProcedure()
082 {
083 if ( procedure == null )
084 {
085 return null;
086 }
087
088 final byte[] copy = new byte[ procedure.length ];
089 System.arraycopy( procedure, 0, copy, 0, procedure.length );
090 return copy;
091 }
092
093
094 public void setProcedure( byte[] procedure )
095 {
096 if ( procedure != null )
097 {
098 this.procedure = new byte[ procedure.length ];
099 System.arraycopy( procedure, 0, this.procedure, 0, procedure.length );
100 } else {
101 this.procedure = null;
102 }
103 }
104
105
106 public List<StoredProcedureParameter> getParameters()
107 {
108 return parameters;
109 }
110
111
112 public void addParameter( StoredProcedureParameter parameter )
113 {
114 parameters.add( parameter );
115 }
116
117
118 public StoredProcedureParameter getCurrentParameter()
119 {
120 return currentParameter;
121 }
122
123
124 public void setCurrentParameter( StoredProcedureParameter currentParameter )
125 {
126 this.currentParameter = currentParameter;
127 }
128
129
130 /**
131 * Bean for representing a Stored Procedure Parameter
132 */
133 public static class StoredProcedureParameter
134 {
135 byte[] type;
136
137 byte[] value;
138
139
140 public byte[] getType()
141 {
142 if ( type == null )
143 {
144 return null;
145 }
146
147 final byte[] copy = new byte[ type.length ];
148 System.arraycopy( type, 0, copy, 0, type.length );
149 return copy;
150 }
151
152
153 public void setType( byte[] type )
154 {
155 if ( type != null )
156 {
157 this.type = new byte[ type.length ];
158 System.arraycopy( type, 0, this.type, 0, type.length );
159 } else {
160 this.type = null;
161 }
162 }
163
164
165 public byte[] getValue()
166 {
167 if ( value == null )
168 {
169 return null;
170 }
171
172 final byte[] copy = new byte[ value.length ];
173 System.arraycopy( value, 0, copy, 0, value.length );
174 return copy;
175 }
176
177
178 public void setValue( byte[] value )
179 {
180 if ( value != null )
181 {
182 this.value = new byte[ value.length ];
183 System.arraycopy( value, 0, this.value, 0, value.length );
184 } else {
185 this.value = null;
186 }
187 }
188 }
189
190 /**
191 * Compute the StoredProcedure length
192 *
193 * 0x30 L1
194 * |
195 * +--> 0x04 L2 language
196 * +--> 0x04 L3 procedure
197 * [+--> 0x30 L4 (parameters)
198 * |
199 * +--> 0x30 L5-1 (parameter)
200 * | |
201 * | +--> 0x04 L6-1 type
202 * | +--> 0x04 L7-1 value
203 * |
204 * +--> 0x30 L5-2 (parameter)
205 * | |
206 * | +--> 0x04 L6-2 type
207 * | +--> 0x04 L7-2 value
208 * |
209 * +--> ...
210 * |
211 * +--> 0x30 L5-m (parameter)
212 * |
213 * +--> 0x04 L6-m type
214 * +--> 0x04 L7-m value
215 */
216 public int computeLength()
217 {
218 // The language
219 byte[] languageBytes = StringTools.getBytesUtf8( language );
220
221 int languageLength = 1 + TLV.getNbBytes( languageBytes.length )
222 + languageBytes.length;
223
224 // The procedure
225 int procedureLength = 1 + TLV.getNbBytes( procedure.length )
226 + procedure.length;
227
228 // Compute parameters length value
229 if ( parameters != null )
230 {
231 parameterLength = new LinkedList<Integer>();
232 paramTypeLength = new LinkedList<Integer>();
233 paramValueLength = new LinkedList<Integer>();
234
235 for ( StoredProcedureParameter spParam:parameters )
236 {
237 int localParameterLength = 0;
238 int localParamTypeLength = 0;
239 int localParamValueLength = 0;
240
241 localParamTypeLength = 1 + TLV.getNbBytes( spParam.type.length ) + spParam.type.length;
242 localParamValueLength = 1 + TLV.getNbBytes( spParam.value.length ) + spParam.value.length;
243
244 localParameterLength = localParamTypeLength + localParamValueLength;
245
246 parametersLength += 1 + TLV.getNbBytes( localParameterLength ) + localParameterLength;
247
248 parameterLength.add( localParameterLength );
249 paramTypeLength.add( localParamTypeLength );
250 paramValueLength.add( localParamValueLength );
251 }
252 }
253
254 int localParametersLength = 1 + TLV.getNbBytes( parametersLength ) + parametersLength;
255 storedProcedureLength = languageLength + procedureLength + localParametersLength;
256
257 return 1 + TLV.getNbBytes( storedProcedureLength ) + storedProcedureLength;
258 }
259
260 /**
261 * Encode the StoredProcedure message to a PDU.
262 *
263 * @param buffer The buffer where to put the PDU
264 * @return The PDU.
265 */
266 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
267 {
268 // Allocate the bytes buffer.
269 ByteBuffer bb = ByteBuffer.allocate( computeLength() );
270
271 try
272 {
273 // The StoredProcedure Tag
274 bb.put( UniversalTag.SEQUENCE_TAG );
275 bb.put( TLV.getBytes( storedProcedureLength ) );
276
277 // The language
278 Value.encode( bb, language );
279
280 // The procedure
281 Value.encode( bb, procedure );
282
283 // The parameters sequence
284 bb.put( UniversalTag.SEQUENCE_TAG );
285 bb.put( TLV.getBytes( parametersLength ) );
286
287 // The parameters list
288 if ( ( parameters != null ) && ( parameters.size() != 0 ) )
289 {
290 int parameterNumber = 0;
291
292 for ( StoredProcedureParameter spParam:parameters )
293 {
294 // The parameter sequence
295 bb.put( UniversalTag.SEQUENCE_TAG );
296 int localParameterLength = parameterLength.get( parameterNumber );
297 bb.put( TLV.getBytes( localParameterLength ) );
298
299 // The parameter type
300 Value.encode( bb, spParam.type );
301
302 // The parameter value
303 Value.encode( bb, spParam.value );
304
305 // Go to the next parameter;
306 parameterNumber++;
307 }
308 }
309 }
310 catch ( BufferOverflowException boe )
311 {
312 throw new EncoderException( "The PDU buffer size is too small !" );
313 }
314
315 return bb;
316 }
317
318
319 /**
320 * Returns the StoredProcedure string
321 *
322 * @return The StoredProcedure string
323 */
324 public String toString()
325 {
326
327 StringBuffer sb = new StringBuffer();
328
329 sb.append( " StoredProcedure\n" );
330 sb.append( " Language : '" ).append( language ).append( "'\n" );
331 sb.append( " Procedure\n" ).append( StringTools.utf8ToString( procedure ) ).append( "'\n" );
332
333 if ( ( parameters == null ) || ( parameters.size() == 0 ) )
334 {
335 sb.append( " No parameters\n" );
336 }
337 else
338 {
339 sb.append( " Parameters\n" );
340
341 int i = 1;
342
343 for ( StoredProcedureParameter spParam:parameters )
344 {
345 sb.append( " type[" ).append( i ) .append( "] : '" ).
346 append( StringTools.utf8ToString( spParam.type ) ).append( "'\n" );
347 sb.append( " value[" ).append( i ) .append( "] : '" ).
348 append( StringTools.dumpBytes( spParam.value ) ).append( "'\n" );
349 }
350 }
351
352 return sb.toString();
353 }
354 }