001/* 002 * Copyright 2008-2014 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2014 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 */ 021package com.unboundid.asn1; 022 023 024 025import com.unboundid.util.NotMutable; 026import com.unboundid.util.ThreadSafety; 027import com.unboundid.util.ThreadSafetyLevel; 028 029import static com.unboundid.asn1.ASN1Constants.*; 030import static com.unboundid.asn1.ASN1Messages.*; 031import 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) 042public 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}