001    /*
002     * Copyright 2007-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2015 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    }