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.i18n.I18n;
036    import org.apache.directory.shared.ldap.util.StringTools;
037    
038    
039    /**
040     * Stored Procedure Extended Operation bean
041     * 
042     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043     * @version $Rev$, $Date$, 
044     */
045    public class StoredProcedure extends AbstractAsn1Object
046    {
047        private String language;
048    
049        private byte[] procedure;
050    
051        private List<StoredProcedureParameter> parameters = new ArrayList<StoredProcedureParameter>();
052    
053        private StoredProcedureParameter currentParameter;
054        
055        /** The stored procedure length */
056        private int storedProcedureLength;
057        
058        /** The parameters length */
059        private int parametersLength;
060    
061        /** The list of all parameter lengths */
062        private List<Integer> parameterLength;
063    
064        /** The list of all parameter type lengths */
065        private List<Integer> paramTypeLength;
066    
067        /** The list of all parameter value lengths */
068        private List<Integer> paramValueLength;
069    
070        public String getLanguage()
071        {
072            return language;
073        }
074    
075    
076        public void setLanguage( String language )
077        {
078            this.language = language;
079        }
080    
081    
082        public byte[] getProcedure()
083        {
084            if ( procedure == null )
085            {
086                return null;
087            }
088    
089            final byte[] copy = new byte[ procedure.length ];
090            System.arraycopy( procedure, 0, copy, 0, procedure.length );
091            return copy;
092        }
093    
094    
095        public void setProcedure( byte[] procedure )
096        {
097            if ( procedure != null )
098            {
099                this.procedure = new byte[ procedure.length ];
100                System.arraycopy( procedure, 0, this.procedure, 0, procedure.length );
101            } else {
102                this.procedure = null;
103            }
104        }
105    
106    
107        public List<StoredProcedureParameter> getParameters()
108        {
109            return parameters;
110        }
111    
112    
113        public void addParameter( StoredProcedureParameter parameter )
114        {
115            parameters.add( parameter );
116        }
117    
118    
119        public StoredProcedureParameter getCurrentParameter()
120        {
121            return currentParameter;
122        }
123    
124    
125        public void setCurrentParameter( StoredProcedureParameter currentParameter )
126        {
127            this.currentParameter = currentParameter;
128        }
129        
130    
131        /**
132         * Bean for representing a Stored Procedure Parameter
133         */
134        public static class StoredProcedureParameter
135        {
136            byte[] type;
137    
138            byte[] value;
139    
140    
141            public byte[] getType()
142            {
143                if ( type == null )
144                {
145                    return null;
146                }
147    
148                final byte[] copy = new byte[ type.length ];
149                System.arraycopy( type, 0, copy, 0, type.length );
150                return copy;
151            }
152    
153    
154            public void setType( byte[] type )
155            {
156                if ( type != null )
157                {
158                    this.type = new byte[ type.length ];
159                    System.arraycopy( type, 0, this.type, 0, type.length );
160                } else {
161                    this.type = null;
162                }
163            }
164    
165    
166            public byte[] getValue()
167            {
168                if ( value == null )
169                {
170                    return null;
171                }
172    
173                final byte[] copy = new byte[ value.length ];
174                System.arraycopy( value, 0, copy, 0, value.length );
175                return copy;
176            }
177    
178    
179            public void setValue( byte[] value )
180            {
181                if ( value != null )
182                {
183                    this.value = new byte[ value.length ];
184                    System.arraycopy( value, 0, this.value, 0, value.length );
185                } else {
186                    this.value = null;
187                }
188            }
189        }
190    
191        /**
192         * Compute the StoredProcedure length 
193         * 
194         * 0x30 L1 
195         *   | 
196         *   +--> 0x04 L2 language
197         *   +--> 0x04 L3 procedure
198         *  [+--> 0x30 L4 (parameters)
199         *          |
200         *          +--> 0x30 L5-1 (parameter)
201         *          |      |
202         *          |      +--> 0x04 L6-1 type
203         *          |      +--> 0x04 L7-1 value
204         *          |      
205         *          +--> 0x30 L5-2 (parameter)
206         *          |      |
207         *          |      +--> 0x04 L6-2 type
208         *          |      +--> 0x04 L7-2 value
209         *          |
210         *          +--> ...
211         *          |      
212         *          +--> 0x30 L5-m (parameter)
213         *                 |
214         *                 +--> 0x04 L6-m type
215         *                 +--> 0x04 L7-m value
216         */
217        public int computeLength()
218        {
219            // The language
220            byte[] languageBytes = StringTools.getBytesUtf8( language );
221            
222            int languageLength = 1 + TLV.getNbBytes( languageBytes.length )
223                + languageBytes.length;
224            
225            // The procedure
226            int procedureLength = 1 + TLV.getNbBytes( procedure.length )
227                + procedure.length;
228            
229            // Compute parameters length value
230            if ( parameters != null )
231            {
232                parameterLength = new LinkedList<Integer>();
233                paramTypeLength = new LinkedList<Integer>();
234                paramValueLength = new LinkedList<Integer>();
235                
236                for ( StoredProcedureParameter spParam:parameters )
237                {
238                    int localParameterLength = 0;
239                    int localParamTypeLength = 0;
240                    int localParamValueLength = 0;
241                    
242                    localParamTypeLength = 1 + TLV.getNbBytes( spParam.type.length ) + spParam.type.length;
243                    localParamValueLength = 1 + TLV.getNbBytes( spParam.value.length ) + spParam.value.length;
244                    
245                    localParameterLength = localParamTypeLength + localParamValueLength;
246                    
247                    parametersLength += 1 + TLV.getNbBytes( localParameterLength ) + localParameterLength;
248                    
249                    parameterLength.add( localParameterLength );
250                    paramTypeLength.add( localParamTypeLength );
251                    paramValueLength.add( localParamValueLength );
252                }
253            }
254            
255            int localParametersLength = 1 + TLV.getNbBytes( parametersLength ) + parametersLength; 
256            storedProcedureLength = languageLength + procedureLength + localParametersLength;
257    
258            return 1 + TLV.getNbBytes( storedProcedureLength ) + storedProcedureLength; 
259        }
260    
261        /**
262         * Encode the StoredProcedure message to a PDU. 
263         * 
264         * @return The PDU.
265         */
266        public ByteBuffer encode() 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( I18n.err( I18n.ERR_04005 ) );
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    }