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 }