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