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