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 */
020package org.apache.directory.api.asn1.ber.tlv;
021
022
023import java.nio.BufferOverflowException;
024import java.nio.ByteBuffer;
025
026import org.apache.directory.api.asn1.EncoderException;
027import org.apache.directory.api.asn1.util.Asn1StringUtils;
028import org.apache.directory.api.asn1.util.BitString;
029import org.apache.directory.api.asn1.util.Oid;
030import org.apache.directory.api.i18n.I18n;
031
032
033/**
034 * This class stores the data decoded from a TLV.
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 */
038public class BerValue
039{
040    /** The data buffer. */
041    private byte[] data;
042
043    /** The current position of the last byte in the data buffer */
044    private int currentPos;
045
046    /** The encoded byte for a TRUE value */
047    public static final byte TRUE_VALUE = ( byte ) 0xFF;
048
049    /** The encoded byte for a FALSE value */
050    public static final byte FALSE_VALUE = ( byte ) 0x00;
051
052    /** Pre-encoded PDUs for a TRUE TLV */
053    private static final byte[] ENCODED_TRUE = new byte[]
054        { 0x01, 0x01, TRUE_VALUE };
055
056    /** Pre-encoded PDUs for a FALSE TLV */
057    private static final byte[] ENCODED_FALSE = new byte[]
058        { 0x01, 0x01, FALSE_VALUE };
059
060    /** Integer limits for encoding : 0x7F */
061    private static final int ONE_BYTE_MAX = ( 1 << 7 ) - 1;
062
063    /** Integer limits for encoding : -0x7F */
064    private static final int ONE_BYTE_MIN = -( 1 << 7 );
065
066    /** Integer limits for encoding : 0x7FFF */
067    private static final int TWO_BYTE_MAX = ( 1 << 15 ) - 1;
068
069    /** Integer limits for encoding : -0x7FFF */
070    private static final int TWO_BYTE_MIN = -( 1 << 15 );
071
072    /** Integer limits for encoding : 0x7FFFFF */
073    private static final int THREE_BYTE_MAX = ( 1 << 23 ) - 1;
074
075    /** Integer limits for encoding : -0x7FFFFF */
076    private static final int THREE_BYTE_MIN = -( 1 << 23 );
077
078    /** Integer limits for encoding : 0x7FFFFFFF */
079    private static final long FOUR_BYTE_MAX = ( 1L << 31 ) - 1L;
080
081    /** Integer limits for encoding : -0x7FFFFFFF */
082    private static final long FOUR_BYTE_MIN = -( 1L << 31 );
083
084    /** Integer limits for encoding : 0x7FFFFFFFFF */
085    private static final long FIVE_BYTE_MAX = ( 1L << 39 ) - 1L;
086
087    /** Integer limits for encoding : -0x7FFFFFFFFF */
088    private static final long FIVE_BYTE_MIN = -( 1L << 39 );
089
090    /** Integer limits for encoding : 0x7FFFFFFFFFFF */
091    private static final long SIX_BYTE_MAX = ( 1L << 47 ) - 1L;
092
093    /** Integer limits for encoding : -0x7FFFFFFFFFFF */
094    private static final long SIX_BYTE_MIN = -( 1L << 47 );
095
096    /** Integer limits for encoding : 0x7FFFFFFFFFFF */
097    private static final long SEVEN_BYTE_MAX = ( 1L << 55 ) - 1L;
098
099    /** Integer limits for encoding : -0x7FFFFFFFFFFF */
100    private static final long SEVEN_BYTE_MIN = -( 1L << 55 );
101
102
103    /**
104     * Creates a new Value from a byte[]
105     *
106     * @param value the associated value
107     */
108    public BerValue( byte[] value )
109    {
110        // Do a copy of the byte array
111        data = new byte[value.length];
112        System.arraycopy( value, 0, data, 0, value.length );
113        currentPos = 0;
114    }
115
116
117    /**
118     * The default constructor.
119     */
120    public BerValue()
121    {
122        data = null;
123        currentPos = 0;
124    }
125
126
127    /**
128     * Initialize the Value
129     *
130     * @param size The data size to allocate.
131     */
132    public void init( int size )
133    {
134        data = new byte[size];
135        currentPos = 0;
136    }
137
138
139    /**
140     * Reset the Value so that it can be reused
141     */
142    public void reset()
143    {
144        data = null;
145        currentPos = 0;
146    }
147
148
149    /**
150     * Get the Values'data
151     *
152     * @return Returns the data.
153     */
154    public byte[] getData()
155    {
156        return data;
157    }
158
159
160    /**
161     * Set a block of bytes in the Value
162     *
163     * @param data The data to set.
164     */
165    public void setData( ByteBuffer data )
166    {
167        int length = data.remaining();
168        data.get( this.data, 0, length );
169        currentPos = length;
170    }
171
172
173    /**
174     * Append some bytes to the data buffer.
175     *
176     * @param buffer The data to append.
177     */
178    public void addData( ByteBuffer buffer )
179    {
180        int length = buffer.remaining();
181        buffer.get( data, currentPos, length );
182        currentPos += length;
183    }
184
185
186    /**
187     * Set a block of bytes in the Value
188     *
189     * @param data The data to set.
190     */
191    public void setData( byte[] data )
192    {
193        System.arraycopy( data, 0, this.data, 0, data.length );
194        currentPos = data.length;
195    }
196
197
198    /**
199     * Append some bytes to the data buffer.
200     *
201     * @param array The data to append.
202     */
203    public void addData( byte[] array )
204    {
205        System.arraycopy( array, 0, this.data, currentPos, array.length );
206        currentPos = array.length;
207    }
208
209
210    /**
211     * @return The number of bytes actually stored
212     */
213    public int getCurrentLength()
214    {
215        return currentPos;
216    }
217
218
219    /**
220     * Utility function that return the number of bytes necessary to store an
221     * integer value. Note that this value must be in [Integer.MIN_VALUE,
222     * Integer.MAX_VALUE].
223     *
224     * @param value The value to store in a byte array
225     * @return The number of bytes necessary to store the value.
226     */
227    public static int getNbBytes( int value )
228    {
229        if ( ( value >= ONE_BYTE_MIN ) && ( value <= ONE_BYTE_MAX ) )
230        {
231            return 1;
232        }
233        else if ( ( value >= TWO_BYTE_MIN ) && ( value <= TWO_BYTE_MAX ) )
234        {
235            return 2;
236        }
237        else if ( ( value >= THREE_BYTE_MIN ) && ( value <= THREE_BYTE_MAX ) )
238        {
239            return 3;
240        }
241        else
242        {
243            return 4;
244        }
245    }
246
247
248    /**
249     * Utility function that return the number of bytes necessary to store a
250     * long value. Note that this value must be in [Long.MIN_VALUE,
251     * Long.MAX_VALUE].
252     *
253     * @param value The value to store in a byte array
254     * @return The number of bytes necessary to store the value.
255     */
256    public static int getNbBytes( long value )
257    {
258        if ( ( value >= ONE_BYTE_MIN ) && ( value <= ONE_BYTE_MAX ) )
259        {
260            return 1;
261        }
262        else if ( ( value >= TWO_BYTE_MIN ) && ( value <= TWO_BYTE_MAX ) )
263        {
264            return 2;
265        }
266        else if ( ( value >= THREE_BYTE_MIN ) && ( value <= THREE_BYTE_MAX ) )
267        {
268            return 3;
269        }
270        else if ( ( value >= FOUR_BYTE_MIN ) && ( value <= FOUR_BYTE_MAX ) )
271        {
272            return 4;
273        }
274        else if ( ( value >= FIVE_BYTE_MIN ) && ( value <= FIVE_BYTE_MAX ) )
275        {
276            return 5;
277        }
278        else if ( ( value >= SIX_BYTE_MIN ) && ( value <= SIX_BYTE_MAX ) )
279        {
280            return 6;
281        }
282        else if ( ( value >= SEVEN_BYTE_MIN ) && ( value <= SEVEN_BYTE_MAX ) )
283        {
284            return 7;
285        }
286        else
287        {
288            return 8;
289        }
290    }
291
292
293    /**
294     * Utility function that return a byte array representing the Value We must
295     * respect the ASN.1 BER encoding scheme :
296     * <pre>
297     * 1) positive integer
298     * - [0 - 0x7F] : 0xVV
299     * - [0x80 - 0xFF] : 0x00 0xVV
300     * - [0x0100 - 0x7FFF] : 0xVV 0xVV
301     * - [0x8000 - 0xFFFF] : 0x00 0xVV 0xVV
302     * - [0x010000 - 0x7FFFFF] : 0xVV 0xVV 0xVV
303     * - [0x800000 - 0xFFFFFF] : 0x00 0xVV 0xVV 0xVV
304     * - [0x01000000 - 0x7FFFFFFF] : 0xVV 0xVV 0xVV 0xVV
305     * 2) Negative number - (~value) + 1
306     * </pre>
307     *
308     * @param value The value to store in a byte array
309     * @return The byte array representing the value.
310     */
311    public static byte[] getBytes( int value )
312    {
313        byte[] bytes = null;
314
315        if ( value >= 0 )
316        {
317            if ( ( value >= 0 ) && ( value <= ONE_BYTE_MAX ) )
318            {
319                bytes = new byte[1];
320                bytes[0] = ( byte ) value;
321            }
322            else if ( ( value > ONE_BYTE_MAX ) && ( value <= TWO_BYTE_MAX ) )
323            {
324                bytes = new byte[2];
325                bytes[1] = ( byte ) value;
326                bytes[0] = ( byte ) ( value >> 8 );
327            }
328            else if ( ( value > TWO_BYTE_MAX ) && ( value <= THREE_BYTE_MAX ) )
329            {
330                bytes = new byte[3];
331                bytes[2] = ( byte ) value;
332                bytes[1] = ( byte ) ( value >> 8 );
333                bytes[0] = ( byte ) ( value >> 16 );
334            }
335            else
336            {
337                bytes = new byte[4];
338                bytes[3] = ( byte ) value;
339                bytes[2] = ( byte ) ( value >> 8 );
340                bytes[1] = ( byte ) ( value >> 16 );
341                bytes[0] = ( byte ) ( value >> 24 );
342            }
343        }
344        else
345        {
346            // On special case : 0x80000000
347            if ( value == 0x80000000 )
348            {
349                bytes = new byte[4];
350                bytes[3] = ( byte ) value;
351                bytes[2] = ( byte ) ( value >> 8 );
352                bytes[1] = ( byte ) ( value >> 16 );
353                bytes[0] = ( byte ) ( value >> 24 );
354            }
355            else
356            {
357                // We have to compute the complement, and add 1
358                //value = ( ~value ) + 1;
359
360                if ( value >= 0xFFFFFF80 )
361                {
362                    bytes = new byte[1];
363                    bytes[0] = ( byte ) value;
364                }
365                else if ( value >= 0xFFFF8000 )
366                {
367                    bytes = new byte[2];
368                    bytes[1] = ( byte ) ( value );
369                    bytes[0] = ( byte ) ( value >> 8 );
370                }
371                else if ( value >= 0xFF800000 )
372                {
373                    bytes = new byte[3];
374                    bytes[2] = ( byte ) value;
375                    bytes[1] = ( byte ) ( value >> 8 );
376                    bytes[0] = ( byte ) ( value >> 16 );
377                }
378                else
379                {
380                    bytes = new byte[4];
381                    bytes[3] = ( byte ) value;
382                    bytes[2] = ( byte ) ( value >> 8 );
383                    bytes[1] = ( byte ) ( value >> 16 );
384                    bytes[0] = ( byte ) ( value >> 24 );
385                }
386            }
387        }
388
389        return bytes;
390    }
391
392
393    /**
394     * Utility function that return a byte array representing the Value.
395     * We must respect the ASN.1 BER encoding scheme : <br>
396     * <pre>
397     * 1) positive integer
398     * - [0 - 0x7F] : 0xVV
399     * - [0x80 - 0xFF] : 0x00 0xVV
400     * - [0x0100 - 0x7FFF] : 0xVV 0xVV
401     * - [0x8000 - 0xFFFF] : 0x00 0xVV 0xVV
402     * - [0x010000 - 0x7FFFFF] : 0xVV 0xVV 0xVV
403     * - [0x800000 - 0xFFFFFF] : 0x00 0xVV 0xVV 0xVV
404     * - [0x01000000 - 0x7FFFFFFF] : 0xVV 0xVV 0xVV 0xVV
405     * 2) Negative number - (~value) + 1
406     * They are encoded following the table (the <br>
407     * encode bytes are those enclosed by squared braquets) :
408    *    -1                      -&gt;FF FF FF FF FF FF FF [FF]
409     *   -127                    -&gt;FF FF FF FF FF FF FF [81]
410     *   -128                    -&gt;FF FF FF FF FF FF FF [80]
411     *   -129                    -&gt;FF FF FF FF FF FF [FF 7F]
412     *   -255                    -&gt;FF FF FF FF FF FF [FF 01]
413     *   -256                    -&gt;FF FF FF FF FF FF [FF 00]
414     *   -257                    -&gt;FF FF FF FF FF FF [FE FF]
415     *   -32767                  -&gt;FF FF FF FF FF FF [80 01]
416     *   -32768                  -&gt;FF FF FF FF FF FF [80 00]
417     *   -32769                  -&gt;FF FF FF FF FF [FF 7F FF]
418     *   -65535                  -&gt;FF FF FF FF FF [FF 00 01]
419     *   -65536                  -&gt;FF FF FF FF FF [FF 00 00]
420     *   -65537                  -&gt;FF FF FF FF FF [FE FF FF]
421     *   -8388607                -&gt;FF FF FF FF FF [80 00 01]
422     *   -8388608                -&gt;FF FF FF FF FF [80 00 00]
423     *   -8388609                -&gt;FF FF FF FF [FF 7F FF FF]
424     *   -16777215               -&gt;FF FF FF FF [FF 00 00 01]
425     *   -16777216               -&gt;FF FF FF FF [FF 00 00 00]
426     *   -16777217               -&gt;FF FF FF FF [FE FF FF FF]
427     *   -2147483647             -&gt;FF FF FF FF [80 00 00 01]
428     *   -2147483648             -&gt;FF FF FF FF [80 00 00 00]
429     *   -2147483649             -&gt;FF FF FF [FF 7F FF FF FF]
430     *   -4294967295             -&gt;FF FF FF [FF 00 00 00 01]
431     *   -4294967296             -&gt;FF FF FF [FF 00 00 00 00]
432     *   -4294967297             -&gt;FF FF FF [FE FF FF FF FF]
433     *   -549755813887           -&gt;FF FF FF [80 00 00 00 01]
434     *   -549755813888           -&gt;FF FF FF [80 00 00 00 00]
435     *   -549755813889           -&gt;FF FF [FF 7F FF FF FF FF]
436     *   -1099511627775          -&gt;FF FF [FF 00 00 00 00 01]
437     *   -1099511627776          -&gt;FF FF [FF 00 00 00 00 00]
438     *   -1099511627777          -&gt;FF FF [FE FF FF FF FF FF]
439     *   -140737488355327        -&gt;FF FF [80 00 00 00 00 01]
440     *   -140737488355328        -&gt;FF FF [80 00 00 00 00 00]
441     *   -140737488355329        -&gt;FF [FF 7F FF FF FF FF FF]
442     *   -281474976710655        -&gt;FF [FF 00 00 00 00 00 01]
443     *   -281474976710656        -&gt;FF [FF 00 00 00 00 00 00]
444     *   -281474976710657        -&gt;FF [FE FF FF FF FF FF FF]
445     *   -36028797018963967      -&gt;FF [80 00 00 00 00 00 01]
446     *   -36028797018963968      -&gt;FF [80 00 00 00 00 00 00]
447     *   -36028797018963969      -&gt;[FF 7F FF FF FF FF FF FF]
448     *   -72057594037927936      -&gt;[FF 00 00 00 00 00 00 00]
449     *   -72057594037927937      -&gt;[FE FF FF FF FF FF FF FF]
450     *   -9223372036854775807    -&gt;[80 00 00 00 00 00 00 01]
451     *   -9223372036854775808    -&gt;[80 00 00 00 00 00 00 00]
452     * </pre>
453     * @param value The value to store in a byte array
454     * @return The byte array representing the value.
455     */
456    public static byte[] getBytes( long value )
457    {
458        byte[] bytes = null;
459
460        if ( value >= 0 )
461        {
462            if ( ( value >= 0 ) && ( value <= ONE_BYTE_MAX ) )
463            {
464                bytes = new byte[1];
465                bytes[0] = ( byte ) value;
466            }
467            else if ( ( value > ONE_BYTE_MAX ) && ( value <= TWO_BYTE_MAX ) )
468            {
469                bytes = new byte[2];
470                bytes[1] = ( byte ) value;
471                bytes[0] = ( byte ) ( value >> 8 );
472            }
473            else if ( ( value > TWO_BYTE_MAX ) && ( value <= THREE_BYTE_MAX ) )
474            {
475                bytes = new byte[3];
476                bytes[2] = ( byte ) value;
477                bytes[1] = ( byte ) ( value >> 8 );
478                bytes[0] = ( byte ) ( value >> 16 );
479            }
480            else if ( ( value > THREE_BYTE_MAX ) && ( value <= FOUR_BYTE_MAX ) )
481            {
482                bytes = new byte[4];
483                bytes[3] = ( byte ) value;
484                bytes[2] = ( byte ) ( value >> 8 );
485                bytes[1] = ( byte ) ( value >> 16 );
486                bytes[0] = ( byte ) ( value >> 24 );
487            }
488            else if ( ( value > FOUR_BYTE_MAX ) && ( value <= FIVE_BYTE_MAX ) )
489            {
490                bytes = new byte[5];
491                bytes[4] = ( byte ) value;
492                bytes[3] = ( byte ) ( value >> 8 );
493                bytes[2] = ( byte ) ( value >> 16 );
494                bytes[1] = ( byte ) ( value >> 24 );
495                bytes[0] = ( byte ) ( value >> 32 );
496            }
497            else if ( ( value > FIVE_BYTE_MAX ) && ( value <= SIX_BYTE_MAX ) )
498            {
499                bytes = new byte[6];
500                bytes[5] = ( byte ) value;
501                bytes[4] = ( byte ) ( value >> 8 );
502                bytes[3] = ( byte ) ( value >> 16 );
503                bytes[2] = ( byte ) ( value >> 24 );
504                bytes[1] = ( byte ) ( value >> 32 );
505                bytes[0] = ( byte ) ( value >> 40 );
506            }
507            else if ( ( value > SIX_BYTE_MAX ) && ( value <= SEVEN_BYTE_MAX ) )
508            {
509                bytes = new byte[7];
510                bytes[6] = ( byte ) value;
511                bytes[5] = ( byte ) ( value >> 8 );
512                bytes[4] = ( byte ) ( value >> 16 );
513                bytes[3] = ( byte ) ( value >> 24 );
514                bytes[2] = ( byte ) ( value >> 32 );
515                bytes[1] = ( byte ) ( value >> 40 );
516                bytes[0] = ( byte ) ( value >> 48 );
517            }
518            else
519            {
520                bytes = new byte[8];
521                bytes[7] = ( byte ) value;
522                bytes[6] = ( byte ) ( value >> 8 );
523                bytes[5] = ( byte ) ( value >> 16 );
524                bytes[4] = ( byte ) ( value >> 24 );
525                bytes[3] = ( byte ) ( value >> 32 );
526                bytes[2] = ( byte ) ( value >> 40 );
527                bytes[1] = ( byte ) ( value >> 48 );
528                bytes[0] = ( byte ) ( value >> 56 );
529            }
530        }
531        else
532        {
533            // On special case : 0x80000000
534            if ( value == 0x8000000000000000L )
535            {
536                bytes = new byte[8];
537                bytes[7] = ( byte ) 0x00;
538                bytes[6] = ( byte ) 0x00;
539                bytes[5] = ( byte ) 0x00;
540                bytes[4] = ( byte ) 0x00;
541                bytes[3] = ( byte ) 0x00;
542                bytes[2] = ( byte ) 0x00;
543                bytes[1] = ( byte ) 0x00;
544                bytes[0] = ( byte ) 0x80;
545            }
546            else
547            {
548                // We have to compute the complement, and add 1
549                // value = ( ~value ) + 1;
550
551                if ( value >= 0xFFFFFFFFFFFFFF80L )
552                {
553                    bytes = new byte[1];
554                    bytes[0] = ( byte ) value;
555                }
556                else if ( value >= 0xFFFFFFFFFFFF8000L )
557                {
558                    bytes = new byte[2];
559                    bytes[1] = ( byte ) ( value );
560                    bytes[0] = ( byte ) ( value >> 8 );
561                }
562                else if ( value >= 0xFFFFFFFFFF800000L )
563                {
564                    bytes = new byte[3];
565                    bytes[2] = ( byte ) value;
566                    bytes[1] = ( byte ) ( value >> 8 );
567                    bytes[0] = ( byte ) ( value >> 16 );
568                }
569                else if ( value >= 0xFFFFFFFF80000000L )
570                {
571                    bytes = new byte[4];
572                    bytes[3] = ( byte ) value;
573                    bytes[2] = ( byte ) ( value >> 8 );
574                    bytes[1] = ( byte ) ( value >> 16 );
575                    bytes[0] = ( byte ) ( value >> 24 );
576                }
577                else if ( value >= 0xFFFFFF8000000000L )
578                {
579                    bytes = new byte[5];
580                    bytes[4] = ( byte ) value;
581                    bytes[3] = ( byte ) ( value >> 8 );
582                    bytes[2] = ( byte ) ( value >> 16 );
583                    bytes[1] = ( byte ) ( value >> 24 );
584                    bytes[0] = ( byte ) ( value >> 32 );
585                }
586                else if ( value >= 0xFFFF800000000000L )
587                {
588                    bytes = new byte[6];
589                    bytes[5] = ( byte ) value;
590                    bytes[4] = ( byte ) ( value >> 8 );
591                    bytes[3] = ( byte ) ( value >> 16 );
592                    bytes[2] = ( byte ) ( value >> 24 );
593                    bytes[1] = ( byte ) ( value >> 32 );
594                    bytes[0] = ( byte ) ( value >> 40 );
595                }
596                else if ( value >= 0xFF80000000000000L )
597                {
598                    bytes = new byte[7];
599                    bytes[6] = ( byte ) value;
600                    bytes[5] = ( byte ) ( value >> 8 );
601                    bytes[4] = ( byte ) ( value >> 16 );
602                    bytes[3] = ( byte ) ( value >> 24 );
603                    bytes[2] = ( byte ) ( value >> 32 );
604                    bytes[1] = ( byte ) ( value >> 40 );
605                    bytes[0] = ( byte ) ( value >> 48 );
606                }
607                else
608                {
609                    bytes = new byte[8];
610                    bytes[7] = ( byte ) value;
611                    bytes[6] = ( byte ) ( value >> 8 );
612                    bytes[5] = ( byte ) ( value >> 16 );
613                    bytes[4] = ( byte ) ( value >> 24 );
614                    bytes[3] = ( byte ) ( value >> 32 );
615                    bytes[2] = ( byte ) ( value >> 40 );
616                    bytes[1] = ( byte ) ( value >> 48 );
617                    bytes[0] = ( byte ) ( value >> 56 );
618                }
619            }
620        }
621
622        return bytes;
623    }
624
625
626    /**
627     * Encode a String value
628     *
629     * @param buffer The PDU in which the value will be put
630     * @param string The String to be encoded. It is supposed to be UTF-8
631     * @throws EncoderException if the PDU in which the value should be encoded is
632     * two small
633     */
634    public static void encode( ByteBuffer buffer, String string ) throws EncoderException
635    {
636        if ( buffer == null )
637        {
638            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
639        }
640
641        try
642        {
643            buffer.put( UniversalTag.OCTET_STRING.getValue() );
644
645            byte[] value = Asn1StringUtils.getBytesUtf8( string );
646
647            buffer.put( TLV.getBytes( value.length ) );
648
649            if ( value.length != 0 )
650            {
651                buffer.put( value );
652            }
653        }
654        catch ( BufferOverflowException boe )
655        {
656            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
657        }
658    }
659
660
661    /**
662     * Encode a BIT STRING value
663     *
664     * @param buffer The PDU in which the value will be put
665     * @param bitString The BitString to be encoded.
666     * @throws EncoderException if the PDU in which the value should be encoded is
667     * two small
668     */
669    public static void encode( ByteBuffer buffer, BitString bitString ) throws EncoderException
670    {
671        if ( buffer == null )
672        {
673            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
674        }
675
676        try
677        {
678            buffer.put( UniversalTag.BIT_STRING.getValue() );
679
680            // The BitString length. We add one byte for the unused number
681            // of bits
682            byte[] bytes = bitString.getData();
683            int length = bytes.length;
684
685            buffer.put( TLV.getBytes( length ) );
686            buffer.put( bytes );
687        }
688        catch ( BufferOverflowException boe )
689        {
690            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
691        }
692    }
693
694
695    /**
696     * Encode an OctetString value
697     *
698     * @param buffer The PDU in which the value will be put
699     * @param bytes The bytes to be encoded
700     * @throws EncoderException if the PDU in which the value should be encoded is
701     * two small
702     */
703    public static void encode( ByteBuffer buffer, byte[] bytes ) throws EncoderException
704    {
705        if ( buffer == null )
706        {
707            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
708        }
709
710        try
711        {
712            buffer.put( UniversalTag.OCTET_STRING.getValue() );
713
714            if ( ( bytes == null ) || ( bytes.length == 0 ) )
715            {
716                buffer.put( ( byte ) 0 );
717            }
718            else
719            {
720                buffer.put( TLV.getBytes( bytes.length ) );
721                buffer.put( bytes );
722            }
723        }
724        catch ( BufferOverflowException boe )
725        {
726            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
727        }
728    }
729
730
731    /**
732     * Encode an OID value
733     *
734     * @param buffer The PDU in which the value will be put
735     * @param oid The OID to be encoded
736     * @throws EncoderException if the PDU in which the value should be encoded is
737     * two small
738     */
739    public static void encode( ByteBuffer buffer, Oid oid ) throws EncoderException
740    {
741        if ( buffer == null )
742        {
743            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
744        }
745
746        try
747        {
748            buffer.put( UniversalTag.OCTET_STRING.getValue() );
749            buffer.put( TLV.getBytes( oid.getEncodedLength() ) );
750
751            if ( oid.getEncodedLength() != 0 )
752            {
753                oid.writeBytesTo( buffer );
754            }
755        }
756        catch ( BufferOverflowException boe )
757        {
758            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
759        }
760    }
761
762
763    /**
764     * Encode an integer value
765     *
766     * @param buffer The PDU in which the value will be put
767     * @param value The integer to be encoded
768     * @throws EncoderException if the PDU in which the value should be encoded is
769     * two small
770     */
771    public static void encode( ByteBuffer buffer, int value ) throws EncoderException
772    {
773        if ( buffer == null )
774        {
775            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
776        }
777
778        try
779        {
780            buffer.put( UniversalTag.INTEGER.getValue() );
781            buffer.put( ( byte ) getNbBytes( value ) );
782            buffer.put( getBytes( value ) );
783        }
784        catch ( BufferOverflowException boe )
785        {
786            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
787        }
788    }
789
790
791    /**
792     * Encode a long value
793     *
794     * @param buffer The PDU in which the value will be put
795     * @param value The long to be encoded
796     * @throws EncoderException if the PDU in which the value should be encoded is
797     * two small
798     */
799    public static void encode( ByteBuffer buffer, long value ) throws EncoderException
800    {
801        if ( buffer == null )
802        {
803            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
804        }
805
806        try
807        {
808            buffer.put( UniversalTag.INTEGER.getValue() );
809            buffer.put( ( byte ) getNbBytes( value ) );
810            buffer.put( getBytes( value ) );
811        }
812        catch ( BufferOverflowException boe )
813        {
814            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
815        }
816    }
817
818
819    /**
820     * Encode an integer value
821     *
822     * @param buffer The PDU in which the value will be put
823     * @param tag The tag if it's not an UNIVERSAL one
824     * @param value The integer to be encoded
825     * @throws EncoderException if the PDU in which the value should be encoded is
826     * two small
827     */
828    public static void encode( ByteBuffer buffer, byte tag, int value ) throws EncoderException
829    {
830        if ( buffer == null )
831        {
832            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
833        }
834
835        try
836        {
837            buffer.put( tag );
838            buffer.put( ( byte ) getNbBytes( value ) );
839            buffer.put( getBytes( value ) );
840        }
841        catch ( BufferOverflowException boe )
842        {
843            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
844        }
845    }
846
847
848    /**
849     * Encode an enumerated value
850     *
851     * @param buffer The PDU in which the value will be put
852     * @param value The integer to be encoded
853     * @throws EncoderException if the PDU in which the value should be encoded is
854     * two small
855     */
856    public static void encodeEnumerated( ByteBuffer buffer, int value ) throws EncoderException
857    {
858        if ( buffer == null )
859        {
860            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
861        }
862
863        try
864        {
865            buffer.put( UniversalTag.ENUMERATED.getValue() );
866            buffer.put( TLV.getBytes( getNbBytes( value ) ) );
867            buffer.put( getBytes( value ) );
868        }
869        catch ( BufferOverflowException boe )
870        {
871            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
872        }
873    }
874
875
876    /**
877     * Encode a boolean value
878     *
879     * @param buffer The PDU in which the value will be put
880     * @param bool The boolean to be encoded
881     * @throws EncoderException if the PDU in which the value should be encoded is
882     * two small
883     */
884    public static void encode( ByteBuffer buffer, boolean bool ) throws EncoderException
885    {
886        if ( buffer == null )
887        {
888            throw new EncoderException( I18n.err( I18n.ERR_00003_CANNOT_PUT_PDU_IN_NULL_BUFFER ) );
889        }
890
891        try
892        {
893            if ( bool )
894            {
895                buffer.put( ENCODED_TRUE );
896            }
897            else
898            {
899                buffer.put( ENCODED_FALSE );
900            }
901        }
902        catch ( BufferOverflowException boe )
903        {
904            throw new EncoderException( I18n.err( I18n.ERR_00004_PDU_BUFFER_SIZE_TOO_SMALL ), boe );
905        }
906    }
907
908
909    /**
910     * Return a string representing the Value
911     *
912     * @return A string representing the value
913     */
914    @Override
915    public String toString()
916    {
917        StringBuilder sb = new StringBuilder();
918        sb.append( "DATA" );
919
920        if ( data != null )
921        {
922            sb.append( '[' );
923            sb.append( Asn1StringUtils.dumpBytes( data ) );
924            sb.append( ']' );
925        }
926        else
927        {
928            return "[]";
929        }
930
931        return sb.toString();
932    }
933}