001    /*
002     * Copyright 2008-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2016 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.asn1;
022    
023    
024    
025    import com.unboundid.util.NotMutable;
026    import com.unboundid.util.ThreadSafety;
027    import com.unboundid.util.ThreadSafetyLevel;
028    
029    import static com.unboundid.asn1.ASN1Constants.*;
030    import static com.unboundid.asn1.ASN1Messages.*;
031    import static com.unboundid.util.Debug.*;
032    
033    
034    
035    /**
036     * This class provides an ASN.1 long element.  It is exactly the same as an
037     * ASN.1 integer, but it uses a 64-bit representation for the decoded value
038     * rather than a 32-bit representation.
039     */
040    @NotMutable()
041    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
042    public final class ASN1Long
043           extends ASN1Element
044    {
045      /**
046       * The serial version UID for this serializable class.
047       */
048      private static final long serialVersionUID = -3445506299288414013L;
049    
050    
051    
052      // The long value for this element.
053      private final long longValue;
054    
055    
056    
057      /**
058       * Creates a new ASN.1 long element with the default BER type and the
059       * provided long value.
060       *
061       * @param  longValue  The long value to use for this element.
062       */
063      public ASN1Long(final long longValue)
064      {
065        super(UNIVERSAL_INTEGER_TYPE, encodeLongValue(longValue));
066    
067        this.longValue = longValue;
068      }
069    
070    
071    
072      /**
073       * Creates a new ASN.1 long element with the specified BER type and the
074       * provided long value.
075       *
076       * @param  type       The BER type to use for this element.
077       * @param  longValue  The long value to use for this element.
078       */
079      public ASN1Long(final byte type, final long longValue)
080      {
081        super(type, encodeLongValue(longValue));
082    
083        this.longValue = longValue;
084      }
085    
086    
087    
088      /**
089       * Creates a new ASN.1 long element with the specified BER type and the
090       * provided long and pre-encoded values.
091       *
092       * @param  type       The BER type to use for this element.
093       * @param  longValue  The long value to use for this element.
094       * @param  value      The pre-encoded value to use for this element.
095       */
096      private ASN1Long(final byte type, final long longValue, final byte[] value)
097      {
098        super(type, value);
099    
100        this.longValue = longValue;
101      }
102    
103    
104    
105      /**
106       * Encodes the provided long value to a byte array suitable for use as the
107       * value of a long element.
108       *
109       * @param  longValue  The long value to be encoded.
110       *
111       * @return  A byte array containing the encoded value.
112       */
113      static byte[] encodeLongValue(final long longValue)
114      {
115        if (longValue < 0)
116        {
117          if ((longValue & 0xFFFFFFFFFFFFFF80L) == 0xFFFFFFFFFFFFFF80L)
118          {
119            return new byte[]
120            {
121              (byte) (longValue & 0xFFL)
122            };
123          }
124          else if ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L)
125          {
126            return new byte[]
127            {
128              (byte) ((longValue >> 8) & 0xFFL),
129              (byte) (longValue & 0xFFL)
130            };
131          }
132          else if ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L)
133          {
134            return new byte[]
135            {
136              (byte) ((longValue >> 16) & 0xFFL),
137              (byte) ((longValue >> 8) & 0xFFL),
138              (byte) (longValue & 0xFFL)
139            };
140          }
141          else if ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L)
142          {
143            return new byte[]
144            {
145              (byte) ((longValue >> 24) & 0xFFL),
146              (byte) ((longValue >> 16) & 0xFFL),
147              (byte) ((longValue >> 8) & 0xFFL),
148              (byte) (longValue & 0xFFL)
149            };
150          }
151          else if ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L)
152          {
153            return new byte[]
154            {
155              (byte) ((longValue >> 32) & 0xFFL),
156              (byte) ((longValue >> 24) & 0xFFL),
157              (byte) ((longValue >> 16) & 0xFFL),
158              (byte) ((longValue >> 8) & 0xFFL),
159              (byte) (longValue & 0xFFL)
160            };
161          }
162          else if ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L)
163          {
164            return new byte[]
165            {
166              (byte) ((longValue >> 40) & 0xFFL),
167              (byte) ((longValue >> 32) & 0xFFL),
168              (byte) ((longValue >> 24) & 0xFFL),
169              (byte) ((longValue >> 16) & 0xFFL),
170              (byte) ((longValue >> 8) & 0xFFL),
171              (byte) (longValue & 0xFFL)
172            };
173          }
174          else if ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L)
175          {
176            return new byte[]
177            {
178              (byte) ((longValue >> 48) & 0xFFL),
179              (byte) ((longValue >> 40) & 0xFFL),
180              (byte) ((longValue >> 32) & 0xFFL),
181              (byte) ((longValue >> 24) & 0xFFL),
182              (byte) ((longValue >> 16) & 0xFFL),
183              (byte) ((longValue >> 8) & 0xFFL),
184              (byte) (longValue & 0xFFL)
185            };
186          }
187          else
188          {
189            return new byte[]
190            {
191              (byte) ((longValue >> 56) & 0xFFL),
192              (byte) ((longValue >> 48) & 0xFFL),
193              (byte) ((longValue >> 40) & 0xFFL),
194              (byte) ((longValue >> 32) & 0xFFL),
195              (byte) ((longValue >> 24) & 0xFFL),
196              (byte) ((longValue >> 16) & 0xFFL),
197              (byte) ((longValue >> 8) & 0xFFL),
198              (byte) (longValue & 0xFFL)
199            };
200          }
201        }
202        else
203        {
204          if ((longValue & 0x000000000000007FL) == longValue)
205          {
206            return new byte[]
207            {
208              (byte) (longValue & 0x7FL)
209            };
210          }
211          else if ((longValue & 0x0000000000007FFFL) == longValue)
212          {
213            return new byte[]
214            {
215              (byte) ((longValue >> 8) & 0x7FL),
216              (byte) (longValue & 0xFFL)
217            };
218          }
219          else if ((longValue & 0x00000000007FFFFFL) == longValue)
220          {
221            return new byte[]
222            {
223              (byte) ((longValue >> 16) & 0x7FL),
224              (byte) ((longValue >> 8) & 0xFFL),
225              (byte) (longValue & 0xFFL)
226            };
227          }
228          else if ((longValue & 0x000000007FFFFFFFL) == longValue)
229          {
230            return new byte[]
231            {
232              (byte) ((longValue >> 24) & 0x7FL),
233              (byte) ((longValue >> 16) & 0xFFL),
234              (byte) ((longValue >> 8) & 0xFFL),
235              (byte) (longValue & 0xFFL)
236            };
237          }
238          else if ((longValue & 0x0000007FFFFFFFFFL) == longValue)
239          {
240            return new byte[]
241            {
242              (byte) ((longValue >> 32) & 0x7FL),
243              (byte) ((longValue >> 24) & 0xFFL),
244              (byte) ((longValue >> 16) & 0xFFL),
245              (byte) ((longValue >> 8) & 0xFFL),
246              (byte) (longValue & 0xFFL)
247            };
248          }
249          else if ((longValue & 0x00007FFFFFFFFFFFL) == longValue)
250          {
251            return new byte[]
252            {
253              (byte) ((longValue >> 40) & 0x7FL),
254              (byte) ((longValue >> 32) & 0xFFL),
255              (byte) ((longValue >> 24) & 0xFFL),
256              (byte) ((longValue >> 16) & 0xFFL),
257              (byte) ((longValue >> 8) & 0xFFL),
258              (byte) (longValue & 0xFFL)
259            };
260          }
261          else if ((longValue & 0x007FFFFFFFFFFFFFL) == longValue)
262          {
263            return new byte[]
264            {
265              (byte) ((longValue >> 48) & 0x7FL),
266              (byte) ((longValue >> 40) & 0xFFL),
267              (byte) ((longValue >> 32) & 0xFFL),
268              (byte) ((longValue >> 24) & 0xFFL),
269              (byte) ((longValue >> 16) & 0xFFL),
270              (byte) ((longValue >> 8) & 0xFFL),
271              (byte) (longValue & 0xFFL)
272            };
273          }
274          else
275          {
276            return new byte[]
277            {
278              (byte) ((longValue >> 56) & 0x7FL),
279              (byte) ((longValue >> 48) & 0xFFL),
280              (byte) ((longValue >> 40) & 0xFFL),
281              (byte) ((longValue >> 32) & 0xFFL),
282              (byte) ((longValue >> 24) & 0xFFL),
283              (byte) ((longValue >> 16) & 0xFFL),
284              (byte) ((longValue >> 8) & 0xFFL),
285              (byte) (longValue & 0xFFL)
286            };
287          }
288        }
289      }
290    
291    
292    
293      /**
294       * Retrieves the long value for this element.
295       *
296       * @return  The long value for this element.
297       */
298      public long longValue()
299      {
300        return longValue;
301      }
302    
303    
304    
305      /**
306       * Decodes the contents of the provided byte array as a long element.
307       *
308       * @param  elementBytes  The byte array to decode as an ASN.1 long element.
309       *
310       * @return  The decoded ASN.1 long element.
311       *
312       * @throws  ASN1Exception  If the provided array cannot be decoded as a long
313       *                         element.
314       */
315      public static ASN1Long decodeAsLong(final byte[] elementBytes)
316             throws ASN1Exception
317      {
318        try
319        {
320          int valueStartPos = 2;
321          int length = (elementBytes[1] & 0x7F);
322          if (length != elementBytes[1])
323          {
324            final int numLengthBytes = length;
325    
326            length = 0;
327            for (int i=0; i < numLengthBytes; i++)
328            {
329              length <<= 8;
330              length |= (elementBytes[valueStartPos++] & 0xFF);
331            }
332          }
333    
334          if ((elementBytes.length - valueStartPos) != length)
335          {
336            throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
337                                         (elementBytes.length - valueStartPos)));
338          }
339    
340          final byte[] value = new byte[length];
341          System.arraycopy(elementBytes, valueStartPos, value, 0, length);
342    
343          long longValue;
344          switch (value.length)
345          {
346            case 1:
347              longValue = (value[0] & 0xFFL);
348              if ((value[0] & 0x80L) != 0x00L)
349              {
350                longValue |= 0xFFFFFFFFFFFFFF00L;
351              }
352              break;
353    
354            case 2:
355              longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL);
356              if ((value[0] & 0x80L) != 0x00L)
357              {
358                longValue |= 0xFFFFFFFFFFFF0000L;
359              }
360              break;
361    
362            case 3:
363              longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) |
364                          (value[2] & 0xFFL);
365              if ((value[0] & 0x80L) != 0x00L)
366              {
367                longValue |= 0xFFFFFFFFFF000000L;
368              }
369              break;
370    
371            case 4:
372              longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) |
373                          ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL);
374              if ((value[0] & 0x80L) != 0x00L)
375              {
376                longValue |= 0xFFFFFFFF00000000L;
377              }
378              break;
379    
380            case 5:
381              longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) |
382                          ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) |
383                          (value[4] & 0xFFL);
384              if ((value[0] & 0x80L) != 0x00L)
385              {
386                longValue |= 0xFFFFFF0000000000L;
387              }
388              break;
389    
390            case 6:
391              longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) |
392                          ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) |
393                          ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL);
394              if ((value[0] & 0x80L) != 0x00L)
395              {
396                longValue |= 0xFFFF000000000000L;
397              }
398              break;
399    
400            case 7:
401              longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) |
402                          ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) |
403                          ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) |
404                          (value[6] & 0xFFL);
405              if ((value[0] & 0x80L) != 0x00L)
406              {
407                longValue |= 0xFF00000000000000L;
408              }
409              break;
410    
411            case 8:
412              longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) |
413                          ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) |
414                          ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) |
415                          ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL);
416              break;
417    
418            default:
419              throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length));
420          }
421    
422          return new ASN1Long(elementBytes[0], longValue, value);
423        }
424        catch (final ASN1Exception ae)
425        {
426          debugException(ae);
427          throw ae;
428        }
429        catch (final Exception e)
430        {
431          debugException(e);
432          throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
433        }
434      }
435    
436    
437    
438      /**
439       * Decodes the provided ASN.1 element as a long element.
440       *
441       * @param  element  The ASN.1 element to be decoded.
442       *
443       * @return  The decoded ASN.1 long element.
444       *
445       * @throws  ASN1Exception  If the provided element cannot be decoded as a long
446       *                         element.
447       */
448      public static ASN1Long decodeAsLong(final ASN1Element element)
449             throws ASN1Exception
450      {
451        long longValue;
452        final byte[] value = element.getValue();
453        switch (value.length)
454        {
455          case 1:
456            longValue = (value[0] & 0xFFL);
457            if ((value[0] & 0x80L) != 0x00L)
458            {
459              longValue |= 0xFFFFFFFFFFFFFF00L;
460            }
461            break;
462    
463          case 2:
464            longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL);
465            if ((value[0] & 0x80L) != 0x00L)
466            {
467              longValue |= 0xFFFFFFFFFFFF0000L;
468            }
469            break;
470    
471          case 3:
472            longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) |
473                        (value[2] & 0xFFL);
474            if ((value[0] & 0x80L) != 0x00L)
475            {
476              longValue |= 0xFFFFFFFFFF000000L;
477            }
478            break;
479    
480          case 4:
481            longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) |
482                        ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL);
483            if ((value[0] & 0x80L) != 0x00L)
484            {
485              longValue |= 0xFFFFFFFF00000000L;
486            }
487            break;
488    
489          case 5:
490            longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) |
491                        ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) |
492                        (value[4] & 0xFFL);
493            if ((value[0] & 0x80L) != 0x00L)
494            {
495              longValue |= 0xFFFFFF0000000000L;
496            }
497            break;
498    
499          case 6:
500            longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) |
501                        ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) |
502                        ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL);
503            if ((value[0] & 0x80L) != 0x00L)
504            {
505              longValue |= 0xFFFF000000000000L;
506            }
507            break;
508    
509          case 7:
510            longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) |
511                        ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) |
512                        ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) |
513                        (value[6] & 0xFFL);
514            if ((value[0] & 0x80L) != 0x00L)
515            {
516              longValue |= 0xFF00000000000000L;
517            }
518            break;
519    
520          case 8:
521            longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) |
522                        ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) |
523                        ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) |
524                        ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL);
525            break;
526    
527          default:
528            throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length));
529        }
530    
531        return new ASN1Long(element.getType(), longValue, value);
532      }
533    
534    
535    
536      /**
537       * Appends a string representation of this ASN.1 element to the provided
538       * buffer.
539       *
540       * @param  buffer  The buffer to which to append the information.
541       */
542      @Override()
543      public void toString(final StringBuilder buffer)
544      {
545        buffer.append(longValue);
546      }
547    }