001 /* 002 * Copyright 2007-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 */ 021 package com.unboundid.asn1; 022 023 024 025 import java.io.InputStream; 026 import java.io.IOException; 027 import java.io.OutputStream; 028 import java.io.Serializable; 029 import java.util.Arrays; 030 031 import com.unboundid.util.ByteStringBuffer; 032 033 import static com.unboundid.asn1.ASN1Constants.*; 034 import static com.unboundid.asn1.ASN1Messages.*; 035 import static com.unboundid.util.Debug.*; 036 import static com.unboundid.util.StaticUtils.*; 037 038 039 040 /** 041 * This class defines a generic ASN.1 BER element, which has a type and value. 042 * It provides a framework for encoding and decoding BER elements, both as 043 * generic elements and more specific subtypes. 044 */ 045 public class ASN1Element 046 implements Serializable 047 { 048 /** 049 * The serial version UID for this serializable class. 050 */ 051 private static final long serialVersionUID = -1871166128693521335L; 052 053 054 055 // The BER type for this element. 056 private final byte type; 057 058 // The encoded value for this element. 059 private final byte[] value; 060 061 // The cached hashCode for this element. 062 private int hashCode = -1; 063 064 // The number of bytes contained in the value. 065 private final int valueLength; 066 067 // The offset within the value array at which the value begins. 068 private final int valueOffset; 069 070 071 072 /** 073 * Creates a new ASN.1 BER element with the specified type and no value. 074 * 075 * @param type The BER type for this element. 076 */ 077 public ASN1Element(final byte type) 078 { 079 this.type = type; 080 value = NO_VALUE; 081 valueOffset = 0; 082 valueLength = 0; 083 } 084 085 086 087 /** 088 * Creates a new ASN1 BER element with the specified type and value. 089 * 090 * @param type The BER type for this element. 091 * @param value The encoded value for this element. 092 */ 093 public ASN1Element(final byte type, final byte[] value) 094 { 095 this.type = type; 096 097 if (value == null) 098 { 099 this.value = NO_VALUE; 100 } 101 else 102 { 103 this.value = value; 104 } 105 106 valueOffset = 0; 107 valueLength = this.value.length; 108 } 109 110 111 112 /** 113 * Creates a new ASN1 BER element with the specified type and value. 114 * 115 * @param type The BER type for this element. 116 * @param value The array containing the encoded value for this element. 117 * It must not be {@code null}. 118 * @param offset The offset within the array at which the value begins. 119 * @param length The number of bytes contained in the value. 120 */ 121 public ASN1Element(final byte type, final byte[] value, final int offset, 122 final int length) 123 { 124 this.type = type; 125 this.value = value; 126 127 valueOffset = offset; 128 valueLength = length; 129 } 130 131 132 133 /** 134 * Retrieves the BER type for this element. 135 * 136 * @return The BER type for this element. 137 */ 138 public final byte getType() 139 { 140 return type; 141 } 142 143 144 145 /** 146 * Retrieves the array containing the value. The returned array may be 147 * larger than the actual value, so it must be used in conjunction with the 148 * values returned by the {@code getValueOffset} and {@code getValueLength} 149 * methods. 150 * 151 * @return The array containing the value. 152 */ 153 byte[] getValueArray() 154 { 155 return value; 156 } 157 158 159 160 /** 161 * Retrieves the position in the value array at which the value actually 162 * begins. 163 * 164 * @return The position in the value array at which the value actually 165 * begins. 166 */ 167 int getValueOffset() 168 { 169 return valueOffset; 170 } 171 172 173 174 /** 175 * Retrieves the number of bytes contained in the value. 176 * 177 * @return The number of bytes contained in the value. 178 */ 179 public int getValueLength() 180 { 181 return valueLength; 182 } 183 184 185 186 /** 187 * Retrieves the encoded value for this element. 188 * 189 * @return The encoded value for this element. 190 */ 191 public byte[] getValue() 192 { 193 if ((valueOffset == 0) && (valueLength == value.length)) 194 { 195 return value; 196 } 197 else 198 { 199 final byte[] returnValue = new byte[valueLength]; 200 System.arraycopy(value, valueOffset, returnValue, 0, valueLength); 201 return returnValue; 202 } 203 } 204 205 206 207 /** 208 * Encodes this ASN.1 element to a byte array. 209 * 210 * @return A byte array containing the encoded representation of this ASN.1 211 * element. 212 */ 213 public final byte[] encode() 214 { 215 final byte[] valueArray = getValueArray(); 216 final int length = getValueLength(); 217 final int offset = getValueOffset(); 218 219 if (length == 0) 220 { 221 return new byte[] { type, 0x00 }; 222 } 223 224 final byte[] lengthBytes = encodeLength(length); 225 final byte[] elementBytes = new byte[1 + lengthBytes.length + length]; 226 227 elementBytes[0] = type; 228 System.arraycopy(lengthBytes, 0, elementBytes, 1, lengthBytes.length); 229 System.arraycopy(valueArray, offset, elementBytes, 1+lengthBytes.length, 230 length); 231 232 return elementBytes; 233 } 234 235 236 237 /** 238 * Encodes the provided length to the given buffer. 239 * 240 * @param length The length to be encoded. 241 * @param buffer The buffer to which the length should be appended. 242 */ 243 static void encodeLengthTo(final int length, final ByteStringBuffer buffer) 244 { 245 if ((length & 0x7F) == length) 246 { 247 buffer.append((byte) length); 248 } 249 else if ((length & 0xFF) == length) 250 { 251 buffer.append((byte) 0x81); 252 buffer.append((byte) (length & 0xFF)); 253 } 254 else if ((length & 0xFFFF) == length) 255 { 256 buffer.append((byte) 0x82); 257 buffer.append((byte) ((length >> 8) & 0xFF)); 258 buffer.append((byte) (length & 0xFF)); 259 } 260 else if ((length & 0xFFFFFF) == length) 261 { 262 buffer.append((byte) 0x83); 263 buffer.append((byte) ((length >> 16) & 0xFF)); 264 buffer.append((byte) ((length >> 8) & 0xFF)); 265 buffer.append((byte) (length & 0xFF)); 266 } 267 else 268 { 269 buffer.append((byte) 0x84); 270 buffer.append((byte) ((length >> 24) & 0xFF)); 271 buffer.append((byte) ((length >> 16) & 0xFF)); 272 buffer.append((byte) ((length >> 8) & 0xFF)); 273 buffer.append((byte) (length & 0xFF)); 274 } 275 } 276 277 278 279 /** 280 * Appends an encoded representation of this ASN.1 element to the provided 281 * buffer. 282 * 283 * @param buffer The buffer to which the encoded representation should be 284 * appended. 285 */ 286 public void encodeTo(final ByteStringBuffer buffer) 287 { 288 final byte[] valueArray = getValueArray(); 289 final int length = getValueLength(); 290 final int offset = getValueOffset(); 291 292 buffer.append(type); 293 if (length == 0) 294 { 295 buffer.append((byte) 0x00); 296 } 297 else 298 { 299 encodeLengthTo(length, buffer); 300 buffer.append(valueArray, offset, length); 301 } 302 } 303 304 305 306 /** 307 * Encodes the provided length to a byte array. 308 * 309 * @param length The length to be encoded. 310 * 311 * @return A byte array containing the encoded length. 312 */ 313 public static byte[] encodeLength(final int length) 314 { 315 switch (length) 316 { 317 case 0: return LENGTH_0; 318 case 1: return LENGTH_1; 319 case 2: return LENGTH_2; 320 case 3: return LENGTH_3; 321 case 4: return LENGTH_4; 322 case 5: return LENGTH_5; 323 case 6: return LENGTH_6; 324 case 7: return LENGTH_7; 325 case 8: return LENGTH_8; 326 case 9: return LENGTH_9; 327 case 10: return LENGTH_10; 328 case 11: return LENGTH_11; 329 case 12: return LENGTH_12; 330 case 13: return LENGTH_13; 331 case 14: return LENGTH_14; 332 case 15: return LENGTH_15; 333 case 16: return LENGTH_16; 334 case 17: return LENGTH_17; 335 case 18: return LENGTH_18; 336 case 19: return LENGTH_19; 337 case 20: return LENGTH_20; 338 case 21: return LENGTH_21; 339 case 22: return LENGTH_22; 340 case 23: return LENGTH_23; 341 case 24: return LENGTH_24; 342 case 25: return LENGTH_25; 343 case 26: return LENGTH_26; 344 case 27: return LENGTH_27; 345 case 28: return LENGTH_28; 346 case 29: return LENGTH_29; 347 case 30: return LENGTH_30; 348 case 31: return LENGTH_31; 349 case 32: return LENGTH_32; 350 case 33: return LENGTH_33; 351 case 34: return LENGTH_34; 352 case 35: return LENGTH_35; 353 case 36: return LENGTH_36; 354 case 37: return LENGTH_37; 355 case 38: return LENGTH_38; 356 case 39: return LENGTH_39; 357 case 40: return LENGTH_40; 358 case 41: return LENGTH_41; 359 case 42: return LENGTH_42; 360 case 43: return LENGTH_43; 361 case 44: return LENGTH_44; 362 case 45: return LENGTH_45; 363 case 46: return LENGTH_46; 364 case 47: return LENGTH_47; 365 case 48: return LENGTH_48; 366 case 49: return LENGTH_49; 367 case 50: return LENGTH_50; 368 case 51: return LENGTH_51; 369 case 52: return LENGTH_52; 370 case 53: return LENGTH_53; 371 case 54: return LENGTH_54; 372 case 55: return LENGTH_55; 373 case 56: return LENGTH_56; 374 case 57: return LENGTH_57; 375 case 58: return LENGTH_58; 376 case 59: return LENGTH_59; 377 case 60: return LENGTH_60; 378 case 61: return LENGTH_61; 379 case 62: return LENGTH_62; 380 case 63: return LENGTH_63; 381 case 64: return LENGTH_64; 382 case 65: return LENGTH_65; 383 case 66: return LENGTH_66; 384 case 67: return LENGTH_67; 385 case 68: return LENGTH_68; 386 case 69: return LENGTH_69; 387 case 70: return LENGTH_70; 388 case 71: return LENGTH_71; 389 case 72: return LENGTH_72; 390 case 73: return LENGTH_73; 391 case 74: return LENGTH_74; 392 case 75: return LENGTH_75; 393 case 76: return LENGTH_76; 394 case 77: return LENGTH_77; 395 case 78: return LENGTH_78; 396 case 79: return LENGTH_79; 397 case 80: return LENGTH_80; 398 case 81: return LENGTH_81; 399 case 82: return LENGTH_82; 400 case 83: return LENGTH_83; 401 case 84: return LENGTH_84; 402 case 85: return LENGTH_85; 403 case 86: return LENGTH_86; 404 case 87: return LENGTH_87; 405 case 88: return LENGTH_88; 406 case 89: return LENGTH_89; 407 case 90: return LENGTH_90; 408 case 91: return LENGTH_91; 409 case 92: return LENGTH_92; 410 case 93: return LENGTH_93; 411 case 94: return LENGTH_94; 412 case 95: return LENGTH_95; 413 case 96: return LENGTH_96; 414 case 97: return LENGTH_97; 415 case 98: return LENGTH_98; 416 case 99: return LENGTH_99; 417 case 100: return LENGTH_100; 418 case 101: return LENGTH_101; 419 case 102: return LENGTH_102; 420 case 103: return LENGTH_103; 421 case 104: return LENGTH_104; 422 case 105: return LENGTH_105; 423 case 106: return LENGTH_106; 424 case 107: return LENGTH_107; 425 case 108: return LENGTH_108; 426 case 109: return LENGTH_109; 427 case 110: return LENGTH_110; 428 case 111: return LENGTH_111; 429 case 112: return LENGTH_112; 430 case 113: return LENGTH_113; 431 case 114: return LENGTH_114; 432 case 115: return LENGTH_115; 433 case 116: return LENGTH_116; 434 case 117: return LENGTH_117; 435 case 118: return LENGTH_118; 436 case 119: return LENGTH_119; 437 case 120: return LENGTH_120; 438 case 121: return LENGTH_121; 439 case 122: return LENGTH_122; 440 case 123: return LENGTH_123; 441 case 124: return LENGTH_124; 442 case 125: return LENGTH_125; 443 case 126: return LENGTH_126; 444 case 127: return LENGTH_127; 445 } 446 447 if ((length & 0x000000FF) == length) 448 { 449 return new byte[] 450 { 451 (byte) 0x81, 452 (byte) (length & 0xFF) 453 }; 454 } 455 else if ((length & 0x0000FFFF) == length) 456 { 457 return new byte[] 458 { 459 (byte) 0x82, 460 (byte) ((length >> 8) & 0xFF), 461 (byte) (length & 0xFF) 462 }; 463 } 464 else if ((length & 0x00FFFFFF) == length) 465 { 466 return new byte[] 467 { 468 (byte) 0x83, 469 (byte) ((length >> 16) & 0xFF), 470 (byte) ((length >> 8) & 0xFF), 471 (byte) (length & 0xFF) 472 }; 473 } 474 else 475 { 476 return new byte[] 477 { 478 (byte) 0x84, 479 (byte) ((length >> 24) & 0xFF), 480 (byte) ((length >> 16) & 0xFF), 481 (byte) ((length >> 8) & 0xFF), 482 (byte) (length & 0xFF) 483 }; 484 } 485 } 486 487 488 489 /** 490 * Decodes the content in the provided byte array as an ASN.1 element. 491 * 492 * @param elementBytes The byte array containing the data to decode. 493 * 494 * @return The decoded ASN.1 BER element. 495 * 496 * @throws ASN1Exception If the provided byte array does not represent a 497 * valid ASN.1 element. 498 */ 499 public static ASN1Element decode(final byte[] elementBytes) 500 throws ASN1Exception 501 { 502 try 503 { 504 int valueStartPos = 2; 505 int length = (elementBytes[1] & 0x7F); 506 if (length != elementBytes[1]) 507 { 508 final int numLengthBytes = length; 509 510 length = 0; 511 for (int i=0; i < numLengthBytes; i++) 512 { 513 length <<= 8; 514 length |= (elementBytes[valueStartPos++] & 0xFF); 515 } 516 } 517 518 if ((elementBytes.length - valueStartPos) != length) 519 { 520 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 521 (elementBytes.length - valueStartPos))); 522 } 523 524 final byte[] value = new byte[length]; 525 System.arraycopy(elementBytes, valueStartPos, value, 0, length); 526 return new ASN1Element(elementBytes[0], value); 527 } 528 catch (final ASN1Exception ae) 529 { 530 debugException(ae); 531 throw ae; 532 } 533 catch (final Exception e) 534 { 535 debugException(e); 536 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 537 } 538 } 539 540 541 542 /** 543 * Decodes this ASN.1 element as a Boolean element. 544 * 545 * @return The decoded Boolean element. 546 * 547 * @throws ASN1Exception If this element cannot be decoded as a Boolean 548 * element. 549 */ 550 public final ASN1Boolean decodeAsBoolean() 551 throws ASN1Exception 552 { 553 return ASN1Boolean.decodeAsBoolean(this); 554 } 555 556 557 558 /** 559 * Decodes this ASN.1 element as an enumerated element. 560 * 561 * @return The decoded enumerated element. 562 * 563 * @throws ASN1Exception If this element cannot be decoded as an enumerated 564 * element. 565 */ 566 public final ASN1Enumerated decodeAsEnumerated() 567 throws ASN1Exception 568 { 569 return ASN1Enumerated.decodeAsEnumerated(this); 570 } 571 572 573 574 /** 575 * Decodes this ASN.1 element as an integer element. 576 * 577 * @return The decoded integer element. 578 * 579 * @throws ASN1Exception If this element cannot be decoded as an integer 580 * element. 581 */ 582 public final ASN1Integer decodeAsInteger() 583 throws ASN1Exception 584 { 585 return ASN1Integer.decodeAsInteger(this); 586 } 587 588 589 590 /** 591 * Decodes this ASN.1 element as a long element. 592 * 593 * @return The decoded long element. 594 * 595 * @throws ASN1Exception If this element cannot be decoded as a long 596 * element. 597 */ 598 public final ASN1Long decodeAsLong() 599 throws ASN1Exception 600 { 601 return ASN1Long.decodeAsLong(this); 602 } 603 604 605 606 /** 607 * Decodes this ASN.1 element as a null element. 608 * 609 * @return The decoded null element. 610 * 611 * @throws ASN1Exception If this element cannot be decoded as a null 612 * element. 613 */ 614 public final ASN1Null decodeAsNull() 615 throws ASN1Exception 616 { 617 return ASN1Null.decodeAsNull(this); 618 } 619 620 621 622 /** 623 * Decodes this ASN.1 element as an octet string element. 624 * 625 * @return The decoded octet string element. 626 */ 627 public final ASN1OctetString decodeAsOctetString() 628 { 629 return ASN1OctetString.decodeAsOctetString(this); 630 } 631 632 633 634 /** 635 * Decodes this ASN.1 element as a sequence element. 636 * 637 * @return The decoded sequence element. 638 * 639 * @throws ASN1Exception If this element cannot be decoded as a sequence 640 * element. 641 */ 642 public final ASN1Sequence decodeAsSequence() 643 throws ASN1Exception 644 { 645 return ASN1Sequence.decodeAsSequence(this); 646 } 647 648 649 650 /** 651 * Decodes this ASN.1 element as a set element. 652 * 653 * @return The decoded set element. 654 * 655 * @throws ASN1Exception If this element cannot be decoded as a set 656 * element. 657 */ 658 public final ASN1Set decodeAsSet() 659 throws ASN1Exception 660 { 661 return ASN1Set.decodeAsSet(this); 662 } 663 664 665 666 /** 667 * Reads an ASN.1 element from the provided input stream. 668 * 669 * @param inputStream The input stream from which to read the element. 670 * 671 * @return The element read from the input stream, or {@code null} if the end 672 * of the input stream is reached without reading any data. 673 * 674 * @throws IOException If a problem occurs while attempting to read from the 675 * input stream. 676 * 677 * @throws ASN1Exception If a problem occurs while attempting to decode the 678 * element. 679 */ 680 public static ASN1Element readFrom(final InputStream inputStream) 681 throws IOException, ASN1Exception 682 { 683 return readFrom(inputStream, -1); 684 } 685 686 687 688 /** 689 * Reads an ASN.1 element from the provided input stream. 690 * 691 * @param inputStream The input stream from which to read the element. 692 * @param maxSize The maximum value size in bytes that will be allowed. 693 * A value less than or equal to zero indicates that no 694 * maximum size should be enforced. An attempt to read 695 * an element with a value larger than this will cause an 696 * {@code ASN1Exception} to be thrown. 697 * 698 * @return The element read from the input stream, or {@code null} if the end 699 * of the input stream is reached without reading any data. 700 * 701 * @throws IOException If a problem occurs while attempting to read from the 702 * input stream. 703 * 704 * @throws ASN1Exception If a problem occurs while attempting to decode the 705 * element. 706 */ 707 public static ASN1Element readFrom(final InputStream inputStream, 708 final int maxSize) 709 throws IOException, ASN1Exception 710 { 711 final int typeInt = inputStream.read(); 712 if (typeInt < 0) 713 { 714 return null; 715 } 716 717 final byte type = (byte) typeInt; 718 719 int length = inputStream.read(); 720 if (length < 0) 721 { 722 throw new ASN1Exception(ERR_READ_END_BEFORE_FIRST_LENGTH.get()); 723 } 724 else if (length > 127) 725 { 726 final int numLengthBytes = length & 0x7F; 727 length = 0; 728 if ((numLengthBytes < 1) || (numLengthBytes > 4)) 729 { 730 throw new ASN1Exception(ERR_READ_LENGTH_TOO_LONG.get(numLengthBytes)); 731 } 732 733 for (int i=0; i < numLengthBytes; i++) 734 { 735 final int lengthInt = inputStream.read(); 736 if (lengthInt < 0) 737 { 738 throw new ASN1Exception(ERR_READ_END_BEFORE_LENGTH_END.get()); 739 } 740 741 length <<= 8; 742 length |= (lengthInt & 0xFF); 743 } 744 } 745 746 if ((length < 0) || ((maxSize > 0) && (length > maxSize))) 747 { 748 throw new ASN1Exception(ERR_READ_LENGTH_EXCEEDS_MAX.get(length, maxSize)); 749 } 750 751 int totalBytesRead = 0; 752 int bytesRemaining = length; 753 final byte[] value = new byte[length]; 754 while (totalBytesRead < length) 755 { 756 final int bytesRead = 757 inputStream.read(value, totalBytesRead, bytesRemaining); 758 if (bytesRead < 0) 759 { 760 throw new ASN1Exception(ERR_READ_END_BEFORE_VALUE_END.get()); 761 } 762 763 totalBytesRead += bytesRead; 764 bytesRemaining -= bytesRead; 765 } 766 767 final ASN1Element e = new ASN1Element(type, value); 768 debugASN1Read(e); 769 return e; 770 } 771 772 773 774 /** 775 * Writes an encoded representation of this ASN.1 element to the provided 776 * output stream. 777 * 778 * @param outputStream The output stream to which the element should be 779 * written. 780 * 781 * @return The total number of bytes written to the output stream. 782 * 783 * @throws IOException If a problem occurs while attempting to write to the 784 * provided output stream. 785 * 786 * @see ASN1Writer#writeElement(ASN1Element,OutputStream) 787 */ 788 public final int writeTo(final OutputStream outputStream) 789 throws IOException 790 { 791 debugASN1Write(this); 792 793 final ByteStringBuffer buffer = new ByteStringBuffer(); 794 encodeTo(buffer); 795 buffer.write(outputStream); 796 return buffer.length(); 797 } 798 799 800 801 /** 802 * Retrieves a hash code for this ASN.1 BER element. 803 * 804 * @return A hash code for this ASN.1 BER element. 805 */ 806 @Override() 807 public final int hashCode() 808 { 809 if (hashCode == -1) 810 { 811 int hash = 0; 812 for (final byte b : getValue()) 813 { 814 hash = hash * 31 + b; 815 } 816 hashCode = hash; 817 } 818 819 return hashCode; 820 } 821 822 823 824 /** 825 * Indicates whether the provided object is equal to this ASN.1 BER element. 826 * The object will only be considered equal to this ASN.1 element if it is a 827 * non-null ASN.1 element with the same type and value as this element. 828 * 829 * @param o The object for which to make the determination. 830 * 831 * @return {@code true} if the provided object is considered equal to this 832 * ASN.1 element, or {@code false} if not. 833 */ 834 @Override() 835 public final boolean equals(final Object o) 836 { 837 if (o == null) 838 { 839 return false; 840 } 841 842 if (o == this) 843 { 844 return true; 845 } 846 847 try 848 { 849 final ASN1Element e = (ASN1Element) o; 850 return ((type == e.getType()) && Arrays.equals(getValue(), e.getValue())); 851 } 852 catch (final Exception e) 853 { 854 debugException(e); 855 return false; 856 } 857 } 858 859 860 861 /** 862 * Indicates whether the provided ASN.1 element is equal to this element, 863 * ignoring any potential difference in the BER type. 864 * 865 * @param element The ASN.1 BER element for which to make the determination. 866 * 867 * @return {@code true} if the provided ASN.1 element is considered equal to 868 * this element (ignoring type differences), or {@code false} if not. 869 */ 870 public final boolean equalsIgnoreType(final ASN1Element element) 871 { 872 if (element == null) 873 { 874 return false; 875 } 876 877 if (element == this) 878 { 879 return true; 880 } 881 882 return Arrays.equals(getValue(), element.getValue()); 883 } 884 885 886 887 /** 888 * Retrieves a string representation of the value for ASN.1 element. 889 * 890 * @return A string representation of the value for this ASN.1 element. 891 */ 892 @Override() 893 public final String toString() 894 { 895 final StringBuilder buffer = new StringBuilder(); 896 toString(buffer); 897 return buffer.toString(); 898 } 899 900 901 902 /** 903 * Appends a string representation of the value for this ASN.1 element to the 904 * provided buffer. 905 * 906 * @param buffer The buffer to which to append the information. 907 */ 908 public void toString(final StringBuilder buffer) 909 { 910 final byte[] v = getValue(); 911 buffer.append("ASN1Element(type="); 912 toHex(type, buffer); 913 buffer.append(", valueLength="); 914 buffer.append(v.length); 915 buffer.append(", valueBytes='"); 916 toHex(v, buffer); 917 buffer.append("')"); 918 } 919 }