001/*
002 * Copyright 2007-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2018 Ping Identity Corporation
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 java.io.InputStream;
026import java.io.IOException;
027import java.io.OutputStream;
028import java.io.Serializable;
029import java.util.Arrays;
030
031import com.unboundid.util.ByteStringBuffer;
032import com.unboundid.util.NotExtensible;
033import com.unboundid.util.NotMutable;
034import com.unboundid.util.ThreadSafety;
035import com.unboundid.util.ThreadSafetyLevel;
036
037import static com.unboundid.asn1.ASN1Constants.*;
038import static com.unboundid.asn1.ASN1Messages.*;
039import static com.unboundid.util.Debug.*;
040import 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)
052public 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 a value that corresponds to the type class for this element.  The
154   * value returned will be one of
155   * {@link ASN1Constants#TYPE_MASK_UNIVERSAL_CLASS},
156   * {@link ASN1Constants#TYPE_MASK_APPLICATION_CLASS},
157   * {@link ASN1Constants#TYPE_MASK_CONTEXT_SPECIFIC_CLASS}, or
158   * {@link ASN1Constants#TYPE_MASK_PRIVATE_CLASS}.
159   *
160   * @return  A value that corresponds to the type class for this element.
161   */
162  public byte getTypeClass()
163  {
164    return (byte) (type & 0xC0);
165  }
166
167
168
169  /**
170   * Indicates whether the type indicates that this element is constructed.  A
171   * constructed element is one whose value is comprised of the encoded
172   * representation of zero or more ASN.1 elements.  If the type does not
173   * indicate that the element is constructed, then the element is considered
174   * primitive.
175   *
176   * @return  {@code true} if the type indicates that the element is
177   *          constructed, or {@code false} if the type indicates that the
178   *          element is primitive.
179   */
180  public boolean isConstructed()
181  {
182    return ((type & ASN1Constants.TYPE_MASK_PC_CONSTRUCTED) != 0x00);
183  }
184
185
186
187  /**
188   * Retrieves the array containing the value.  The returned array may be
189   * larger than the actual value, so it must be used in conjunction with the
190   * values returned by the {@link #getValueOffset} and {@link #getValueLength}
191   * methods.
192   *
193   * @return  The array containing the value.
194   */
195  byte[] getValueArray()
196  {
197    return value;
198  }
199
200
201
202  /**
203   * Retrieves the position in the value array at which the value actually
204   * begins.
205   *
206   * @return  The position in the value array at which the value actually
207   *          begins.
208   */
209  int getValueOffset()
210  {
211    return valueOffset;
212  }
213
214
215
216  /**
217   * Retrieves the number of bytes contained in the value.
218   *
219   * @return  The number of bytes contained in the value.
220   */
221  public int getValueLength()
222  {
223    return valueLength;
224  }
225
226
227
228  /**
229   * Retrieves the encoded value for this element.
230   *
231   * @return  The encoded value for this element.
232   */
233  public byte[] getValue()
234  {
235    if ((valueOffset == 0) && (valueLength == value.length))
236    {
237      return value;
238    }
239    else
240    {
241      final byte[] returnValue = new byte[valueLength];
242      System.arraycopy(value, valueOffset, returnValue, 0, valueLength);
243      return returnValue;
244    }
245  }
246
247
248
249  /**
250   * Encodes this ASN.1 element to a byte array.
251   *
252   * @return  A byte array containing the encoded representation of this ASN.1
253   *          element.
254   */
255  public final byte[] encode()
256  {
257    final byte[] valueArray = getValueArray();
258    final int    length     = getValueLength();
259    final int    offset     = getValueOffset();
260
261    if (length == 0)
262    {
263      return new byte[] { type, 0x00 };
264    }
265
266    final byte[] lengthBytes  = encodeLength(length);
267    final byte[] elementBytes = new byte[1 + lengthBytes.length + length];
268
269    elementBytes[0] = type;
270    System.arraycopy(lengthBytes, 0, elementBytes, 1, lengthBytes.length);
271    System.arraycopy(valueArray, offset, elementBytes, 1+lengthBytes.length,
272         length);
273
274    return elementBytes;
275  }
276
277
278
279  /**
280   * Encodes the provided length to the given buffer.
281   *
282   * @param  length  The length to be encoded.
283   * @param  buffer  The buffer to which the length should be appended.
284   */
285  static void encodeLengthTo(final int length, final ByteStringBuffer buffer)
286  {
287    if ((length & 0x7F) == length)
288    {
289      buffer.append((byte) length);
290    }
291    else if ((length & 0xFF) == length)
292    {
293      buffer.append((byte) 0x81);
294      buffer.append((byte) (length & 0xFF));
295    }
296    else if ((length & 0xFFFF) == length)
297    {
298      buffer.append((byte) 0x82);
299      buffer.append((byte) ((length >> 8) & 0xFF));
300      buffer.append((byte) (length & 0xFF));
301    }
302    else if ((length & 0xFFFFFF) == length)
303    {
304      buffer.append((byte) 0x83);
305      buffer.append((byte) ((length >> 16) & 0xFF));
306      buffer.append((byte) ((length >> 8) & 0xFF));
307      buffer.append((byte) (length & 0xFF));
308    }
309    else
310    {
311      buffer.append((byte) 0x84);
312      buffer.append((byte) ((length >> 24) & 0xFF));
313      buffer.append((byte) ((length >> 16) & 0xFF));
314      buffer.append((byte) ((length >> 8) & 0xFF));
315      buffer.append((byte) (length & 0xFF));
316    }
317  }
318
319
320
321  /**
322   * Appends an encoded representation of this ASN.1 element to the provided
323   * buffer.
324   *
325   * @param  buffer  The buffer to which the encoded representation should be
326   *                 appended.
327   */
328  public void encodeTo(final ByteStringBuffer buffer)
329  {
330    final byte[] valueArray = getValueArray();
331    final int    length     = getValueLength();
332    final int    offset     = getValueOffset();
333
334    buffer.append(type);
335    if (length == 0)
336    {
337      buffer.append((byte) 0x00);
338    }
339    else
340    {
341      encodeLengthTo(length, buffer);
342      buffer.append(valueArray, offset, length);
343    }
344  }
345
346
347
348  /**
349   * Encodes the provided length to a byte array.
350   *
351   * @param  length  The length to be encoded.
352   *
353   * @return  A byte array containing the encoded length.
354   */
355  public static byte[] encodeLength(final int length)
356  {
357    switch (length)
358    {
359      case 0:  return LENGTH_0;
360      case 1:  return LENGTH_1;
361      case 2:  return LENGTH_2;
362      case 3:  return LENGTH_3;
363      case 4:  return LENGTH_4;
364      case 5:  return LENGTH_5;
365      case 6:  return LENGTH_6;
366      case 7:  return LENGTH_7;
367      case 8:  return LENGTH_8;
368      case 9:  return LENGTH_9;
369      case 10:  return LENGTH_10;
370      case 11:  return LENGTH_11;
371      case 12:  return LENGTH_12;
372      case 13:  return LENGTH_13;
373      case 14:  return LENGTH_14;
374      case 15:  return LENGTH_15;
375      case 16:  return LENGTH_16;
376      case 17:  return LENGTH_17;
377      case 18:  return LENGTH_18;
378      case 19:  return LENGTH_19;
379      case 20:  return LENGTH_20;
380      case 21:  return LENGTH_21;
381      case 22:  return LENGTH_22;
382      case 23:  return LENGTH_23;
383      case 24:  return LENGTH_24;
384      case 25:  return LENGTH_25;
385      case 26:  return LENGTH_26;
386      case 27:  return LENGTH_27;
387      case 28:  return LENGTH_28;
388      case 29:  return LENGTH_29;
389      case 30:  return LENGTH_30;
390      case 31:  return LENGTH_31;
391      case 32:  return LENGTH_32;
392      case 33:  return LENGTH_33;
393      case 34:  return LENGTH_34;
394      case 35:  return LENGTH_35;
395      case 36:  return LENGTH_36;
396      case 37:  return LENGTH_37;
397      case 38:  return LENGTH_38;
398      case 39:  return LENGTH_39;
399      case 40:  return LENGTH_40;
400      case 41:  return LENGTH_41;
401      case 42:  return LENGTH_42;
402      case 43:  return LENGTH_43;
403      case 44:  return LENGTH_44;
404      case 45:  return LENGTH_45;
405      case 46:  return LENGTH_46;
406      case 47:  return LENGTH_47;
407      case 48:  return LENGTH_48;
408      case 49:  return LENGTH_49;
409      case 50:  return LENGTH_50;
410      case 51:  return LENGTH_51;
411      case 52:  return LENGTH_52;
412      case 53:  return LENGTH_53;
413      case 54:  return LENGTH_54;
414      case 55:  return LENGTH_55;
415      case 56:  return LENGTH_56;
416      case 57:  return LENGTH_57;
417      case 58:  return LENGTH_58;
418      case 59:  return LENGTH_59;
419      case 60:  return LENGTH_60;
420      case 61:  return LENGTH_61;
421      case 62:  return LENGTH_62;
422      case 63:  return LENGTH_63;
423      case 64:  return LENGTH_64;
424      case 65:  return LENGTH_65;
425      case 66:  return LENGTH_66;
426      case 67:  return LENGTH_67;
427      case 68:  return LENGTH_68;
428      case 69:  return LENGTH_69;
429      case 70:  return LENGTH_70;
430      case 71:  return LENGTH_71;
431      case 72:  return LENGTH_72;
432      case 73:  return LENGTH_73;
433      case 74:  return LENGTH_74;
434      case 75:  return LENGTH_75;
435      case 76:  return LENGTH_76;
436      case 77:  return LENGTH_77;
437      case 78:  return LENGTH_78;
438      case 79:  return LENGTH_79;
439      case 80:  return LENGTH_80;
440      case 81:  return LENGTH_81;
441      case 82:  return LENGTH_82;
442      case 83:  return LENGTH_83;
443      case 84:  return LENGTH_84;
444      case 85:  return LENGTH_85;
445      case 86:  return LENGTH_86;
446      case 87:  return LENGTH_87;
447      case 88:  return LENGTH_88;
448      case 89:  return LENGTH_89;
449      case 90:  return LENGTH_90;
450      case 91:  return LENGTH_91;
451      case 92:  return LENGTH_92;
452      case 93:  return LENGTH_93;
453      case 94:  return LENGTH_94;
454      case 95:  return LENGTH_95;
455      case 96:  return LENGTH_96;
456      case 97:  return LENGTH_97;
457      case 98:  return LENGTH_98;
458      case 99:  return LENGTH_99;
459      case 100:  return LENGTH_100;
460      case 101:  return LENGTH_101;
461      case 102:  return LENGTH_102;
462      case 103:  return LENGTH_103;
463      case 104:  return LENGTH_104;
464      case 105:  return LENGTH_105;
465      case 106:  return LENGTH_106;
466      case 107:  return LENGTH_107;
467      case 108:  return LENGTH_108;
468      case 109:  return LENGTH_109;
469      case 110:  return LENGTH_110;
470      case 111:  return LENGTH_111;
471      case 112:  return LENGTH_112;
472      case 113:  return LENGTH_113;
473      case 114:  return LENGTH_114;
474      case 115:  return LENGTH_115;
475      case 116:  return LENGTH_116;
476      case 117:  return LENGTH_117;
477      case 118:  return LENGTH_118;
478      case 119:  return LENGTH_119;
479      case 120:  return LENGTH_120;
480      case 121:  return LENGTH_121;
481      case 122:  return LENGTH_122;
482      case 123:  return LENGTH_123;
483      case 124:  return LENGTH_124;
484      case 125:  return LENGTH_125;
485      case 126:  return LENGTH_126;
486      case 127:  return LENGTH_127;
487    }
488
489    if ((length & 0x000000FF) == length)
490    {
491      return new byte[]
492      {
493        (byte) 0x81,
494        (byte) (length & 0xFF)
495      };
496    }
497    else if ((length & 0x0000FFFF) == length)
498    {
499      return new byte[]
500      {
501        (byte) 0x82,
502        (byte) ((length >> 8) & 0xFF),
503        (byte) (length & 0xFF)
504      };
505    }
506    else if ((length & 0x00FFFFFF) == length)
507    {
508      return new byte[]
509      {
510        (byte) 0x83,
511        (byte) ((length >> 16) & 0xFF),
512        (byte) ((length >> 8) & 0xFF),
513        (byte) (length & 0xFF)
514      };
515    }
516    else
517    {
518      return new byte[]
519      {
520        (byte) 0x84,
521        (byte) ((length >> 24) & 0xFF),
522        (byte) ((length >> 16) & 0xFF),
523        (byte) ((length >> 8) & 0xFF),
524        (byte) (length & 0xFF)
525      };
526    }
527  }
528
529
530
531  /**
532   * Decodes the content in the provided byte array as an ASN.1 element.
533   *
534   * @param  elementBytes  The byte array containing the data to decode.
535   *
536   * @return  The decoded ASN.1 BER element.
537   *
538   * @throws  ASN1Exception  If the provided byte array does not represent a
539   *                         valid ASN.1 element.
540   */
541  public static ASN1Element decode(final byte[] elementBytes)
542         throws ASN1Exception
543  {
544    try
545    {
546      int valueStartPos = 2;
547      int length = (elementBytes[1] & 0x7F);
548      if (length != elementBytes[1])
549      {
550        final int numLengthBytes = length;
551
552        length = 0;
553        for (int i=0; i < numLengthBytes; i++)
554        {
555          length <<= 8;
556          length |= (elementBytes[valueStartPos++] & 0xFF);
557        }
558      }
559
560      if ((elementBytes.length - valueStartPos) != length)
561      {
562        throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
563                                     (elementBytes.length - valueStartPos)));
564      }
565
566      final byte[] value = new byte[length];
567      System.arraycopy(elementBytes, valueStartPos, value, 0, length);
568      return new ASN1Element(elementBytes[0], value);
569    }
570    catch (final ASN1Exception ae)
571    {
572      debugException(ae);
573      throw ae;
574    }
575    catch (final Exception e)
576    {
577      debugException(e);
578      throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
579    }
580  }
581
582
583
584  /**
585   * Decodes this ASN.1 element as a bit string element.
586   *
587   * @return  The decoded bit string element.
588   *
589   * @throws  ASN1Exception  If this element cannot be decoded as a bit string
590   *                         element.
591   */
592  public final ASN1BitString decodeAsBitString()
593         throws ASN1Exception
594  {
595    return ASN1BitString.decodeAsBitString(this);
596  }
597
598
599
600  /**
601   * Decodes this ASN.1 element as a Boolean element.
602   *
603   * @return  The decoded Boolean element.
604   *
605   * @throws  ASN1Exception  If this element cannot be decoded as a Boolean
606   *                         element.
607   */
608  public final ASN1Boolean decodeAsBoolean()
609         throws ASN1Exception
610  {
611    return ASN1Boolean.decodeAsBoolean(this);
612  }
613
614
615
616  /**
617   * Decodes this ASN.1 element as an enumerated element.
618   *
619   * @return  The decoded enumerated element.
620   *
621   * @throws  ASN1Exception  If this element cannot be decoded as an enumerated
622   *                         element.
623   */
624  public final ASN1Enumerated decodeAsEnumerated()
625         throws ASN1Exception
626  {
627    return ASN1Enumerated.decodeAsEnumerated(this);
628  }
629
630
631
632  /**
633   * Decodes this ASN.1 element as a generalized time element.
634   *
635   * @return  The decoded generalized time element.
636   *
637   * @throws  ASN1Exception  If this element cannot be decoded as a generalized
638   *                         time element.
639   */
640  public final ASN1GeneralizedTime decodeAsGeneralizedTime()
641         throws ASN1Exception
642  {
643    return ASN1GeneralizedTime.decodeAsGeneralizedTime(this);
644  }
645
646
647
648  /**
649   * Decodes this ASN.1 element as an IA5 string element.
650   *
651   * @return  The decoded IA5 string element.
652   *
653   * @throws  ASN1Exception  If this element cannot be decoded as a IA5 string
654   *                         element.
655   */
656  public final ASN1IA5String decodeAsIA5String()
657         throws ASN1Exception
658  {
659    return ASN1IA5String.decodeAsIA5String(this);
660  }
661
662
663
664  /**
665   * Decodes this ASN.1 element as an integer element.
666   *
667   * @return  The decoded integer element.
668   *
669   * @throws  ASN1Exception  If this element cannot be decoded as an integer
670   *                         element.
671   */
672  public final ASN1Integer decodeAsInteger()
673         throws ASN1Exception
674  {
675    return ASN1Integer.decodeAsInteger(this);
676  }
677
678
679
680  /**
681   * Decodes this ASN.1 element as a long element.
682   *
683   * @return  The decoded long element.
684   *
685   * @throws  ASN1Exception  If this element cannot be decoded as a long
686   *                         element.
687   */
688  public final ASN1Long decodeAsLong()
689         throws ASN1Exception
690  {
691    return ASN1Long.decodeAsLong(this);
692  }
693
694
695
696  /**
697   * Decodes this ASN.1 element as a big integer element.
698   *
699   * @return  The decoded big integer element.
700   *
701   * @throws  ASN1Exception  If this element cannot be decoded as a big integer
702   *                         element.
703   */
704  public final ASN1BigInteger decodeAsBigInteger()
705         throws ASN1Exception
706  {
707    return ASN1BigInteger.decodeAsBigInteger(this);
708  }
709
710
711
712  /**
713   * Decodes this ASN.1 element as a null element.
714   *
715   * @return  The decoded null element.
716   *
717   * @throws  ASN1Exception  If this element cannot be decoded as a null
718   *                         element.
719   */
720  public final ASN1Null decodeAsNull()
721         throws ASN1Exception
722  {
723    return ASN1Null.decodeAsNull(this);
724  }
725
726
727
728  /**
729   * Decodes this ASN.1 element as a numeric string element.
730   *
731   * @return  The decoded numeric string element.
732   *
733   * @throws  ASN1Exception  If this element cannot be decoded as a numeric
734   *                         string element.
735   */
736  public final ASN1NumericString decodeAsNumericString()
737         throws ASN1Exception
738  {
739    return ASN1NumericString.decodeAsNumericString(this);
740  }
741
742
743
744  /**
745   * Decodes this ASN.1 element as an object identifier element.
746   *
747   * @return  The decoded object identifier element.
748   *
749   * @throws  ASN1Exception  If this element cannot be decoded as an object
750   *                         identifier element.
751   */
752  public final ASN1ObjectIdentifier decodeAsObjectIdentifier()
753         throws ASN1Exception
754  {
755    return ASN1ObjectIdentifier.decodeAsObjectIdentifier(this);
756  }
757
758
759
760  /**
761   * Decodes this ASN.1 element as an octet string element.
762   *
763   * @return  The decoded octet string element.
764   */
765  public final ASN1OctetString decodeAsOctetString()
766  {
767    return ASN1OctetString.decodeAsOctetString(this);
768  }
769
770
771
772  /**
773   * Decodes this ASN.1 element as a printable string element.
774   *
775   * @return  The decoded printable string element.
776   *
777   * @throws  ASN1Exception  If this element cannot be decoded as a printable
778   *                         string element.
779   */
780  public final ASN1PrintableString decodeAsPrintableString()
781         throws ASN1Exception
782  {
783    return ASN1PrintableString.decodeAsPrintableString(this);
784  }
785
786
787
788  /**
789   * Decodes this ASN.1 element as a sequence element.
790   *
791   * @return  The decoded sequence element.
792   *
793   * @throws  ASN1Exception  If this element cannot be decoded as a sequence
794   *                         element.
795   */
796  public final ASN1Sequence decodeAsSequence()
797         throws ASN1Exception
798  {
799    return ASN1Sequence.decodeAsSequence(this);
800  }
801
802
803
804  /**
805   * Decodes this ASN.1 element as a set element.
806   *
807   * @return  The decoded set element.
808   *
809   * @throws  ASN1Exception  If this element cannot be decoded as a set
810   *                         element.
811   */
812  public final ASN1Set decodeAsSet()
813         throws ASN1Exception
814  {
815    return ASN1Set.decodeAsSet(this);
816  }
817
818
819
820  /**
821   * Decodes this ASN.1 element as a UTC time element.
822   *
823   * @return  The decoded UTC time element.
824   *
825   * @throws  ASN1Exception  If this element cannot be decoded as a UTC time
826   *                         element.
827   */
828  public final ASN1UTCTime decodeAsUTCTime()
829         throws ASN1Exception
830  {
831    return ASN1UTCTime.decodeAsUTCTime(this);
832  }
833
834
835
836  /**
837   * Decodes this ASN.1 element as a UTF-8 string element.
838   *
839   * @return  The decoded UTF_8 string element.
840   *
841   * @throws  ASN1Exception  If this element cannot be decoded as a UTF-8
842   *                         string element.
843   */
844  public final ASN1UTF8String decodeAsUTF8String()
845         throws ASN1Exception
846  {
847    return ASN1UTF8String.decodeAsUTF8String(this);
848  }
849
850
851
852  /**
853   * Reads an ASN.1 element from the provided input stream.
854   *
855   * @param  inputStream  The input stream from which to read the element.
856   *
857   * @return  The element read from the input stream, or {@code null} if the end
858   *          of the input stream is reached without reading any data.
859   *
860   * @throws  IOException  If a problem occurs while attempting to read from the
861   *                       input stream.
862   *
863   * @throws  ASN1Exception  If a problem occurs while attempting to decode the
864   *                         element.
865   */
866  public static ASN1Element readFrom(final InputStream inputStream)
867         throws IOException, ASN1Exception
868  {
869    return readFrom(inputStream, -1);
870  }
871
872
873
874  /**
875   * Reads an ASN.1 element from the provided input stream.
876   *
877   * @param  inputStream  The input stream from which to read the element.
878   * @param  maxSize      The maximum value size in bytes that will be allowed.
879   *                      A value less than or equal to zero indicates that no
880   *                      maximum size should be enforced.  An attempt to read
881   *                      an element with a value larger than this will cause an
882   *                      {@code ASN1Exception} to be thrown.
883   *
884   * @return  The element read from the input stream, or {@code null} if the end
885   *          of the input stream is reached without reading any data.
886   *
887   * @throws  IOException  If a problem occurs while attempting to read from the
888   *                       input stream.
889   *
890   * @throws  ASN1Exception  If a problem occurs while attempting to decode the
891   *                         element.
892   */
893  public static ASN1Element readFrom(final InputStream inputStream,
894                                     final int maxSize)
895         throws IOException, ASN1Exception
896  {
897    final int typeInt = inputStream.read();
898    if (typeInt < 0)
899    {
900      return null;
901    }
902
903    final byte type = (byte) typeInt;
904
905    int length = inputStream.read();
906    if (length < 0)
907    {
908      throw new ASN1Exception(ERR_READ_END_BEFORE_FIRST_LENGTH.get());
909    }
910    else if (length > 127)
911    {
912      final int numLengthBytes = length & 0x7F;
913      length = 0;
914      if ((numLengthBytes < 1) || (numLengthBytes > 4))
915      {
916        throw new ASN1Exception(ERR_READ_LENGTH_TOO_LONG.get(numLengthBytes));
917      }
918
919      for (int i=0; i < numLengthBytes; i++)
920      {
921        final int lengthInt = inputStream.read();
922        if (lengthInt < 0)
923        {
924          throw new ASN1Exception(ERR_READ_END_BEFORE_LENGTH_END.get());
925        }
926
927        length <<= 8;
928        length |= (lengthInt & 0xFF);
929      }
930    }
931
932    if ((length < 0) || ((maxSize > 0) && (length > maxSize)))
933    {
934      throw new ASN1Exception(ERR_READ_LENGTH_EXCEEDS_MAX.get(length, maxSize));
935    }
936
937    int totalBytesRead = 0;
938    int bytesRemaining = length;
939    final byte[] value = new byte[length];
940    while (totalBytesRead < length)
941    {
942      final int bytesRead =
943           inputStream.read(value, totalBytesRead, bytesRemaining);
944      if (bytesRead < 0)
945      {
946        throw new ASN1Exception(ERR_READ_END_BEFORE_VALUE_END.get());
947      }
948
949      totalBytesRead += bytesRead;
950      bytesRemaining -= bytesRead;
951    }
952
953    final ASN1Element e = new ASN1Element(type, value);
954    debugASN1Read(e);
955    return e;
956  }
957
958
959
960  /**
961   * Writes an encoded representation of this ASN.1 element to the provided
962   * output stream.
963   *
964   * @param  outputStream  The output stream to which the element should be
965   *                       written.
966   *
967   * @return  The total number of bytes written to the output stream.
968   *
969   * @throws  IOException  If a problem occurs while attempting to write to the
970   *                       provided output stream.
971   *
972   * @see  ASN1Writer#writeElement(ASN1Element,OutputStream)
973   */
974  public final int writeTo(final OutputStream outputStream)
975         throws IOException
976  {
977    debugASN1Write(this);
978
979    final ByteStringBuffer buffer = new ByteStringBuffer();
980    encodeTo(buffer);
981    buffer.write(outputStream);
982    return buffer.length();
983  }
984
985
986
987  /**
988   * Retrieves a hash code for this ASN.1 BER element.
989   *
990   * @return  A hash code for this ASN.1 BER element.
991   */
992  @Override()
993  public final int hashCode()
994  {
995    if (hashCode == -1)
996    {
997      int hash = 0;
998      for (final byte b : getValue())
999      {
1000        hash = hash * 31 + b;
1001      }
1002      hashCode = hash;
1003    }
1004
1005    return hashCode;
1006  }
1007
1008
1009
1010  /**
1011   * Indicates whether the provided object is equal to this ASN.1 BER element.
1012   * The object will only be considered equal to this ASN.1 element if it is a
1013   * non-null ASN.1 element with the same type and value as this element.
1014   *
1015   * @param  o  The object for which to make the determination.
1016   *
1017   * @return  {@code true} if the provided object is considered equal to this
1018   *          ASN.1 element, or {@code false} if not.
1019   */
1020  @Override()
1021  public final boolean equals(final Object o)
1022  {
1023    if (o == null)
1024    {
1025      return false;
1026    }
1027
1028    if (o == this)
1029    {
1030      return true;
1031    }
1032
1033    try
1034    {
1035      final ASN1Element e = (ASN1Element) o;
1036      return ((type == e.getType()) && Arrays.equals(getValue(), e.getValue()));
1037    }
1038    catch (final Exception e)
1039    {
1040      debugException(e);
1041      return false;
1042    }
1043  }
1044
1045
1046
1047  /**
1048   * Indicates whether the provided ASN.1 element is equal to this element,
1049   * ignoring any potential difference in the BER type.
1050   *
1051   * @param  element  The ASN.1 BER element for which to make the determination.
1052   *
1053   * @return  {@code true} if the provided ASN.1 element is considered equal to
1054   *          this element (ignoring type differences), or {@code false} if not.
1055   */
1056  public final boolean equalsIgnoreType(final ASN1Element element)
1057  {
1058    if (element == null)
1059    {
1060      return false;
1061    }
1062
1063    if (element == this)
1064    {
1065      return true;
1066    }
1067
1068    return Arrays.equals(getValue(), element.getValue());
1069  }
1070
1071
1072
1073  /**
1074   * Retrieves a string representation of the value for ASN.1 element.
1075   *
1076   * @return  A string representation of the value for this ASN.1 element.
1077   */
1078  @Override()
1079  public final String toString()
1080  {
1081    final StringBuilder buffer = new StringBuilder();
1082    toString(buffer);
1083    return buffer.toString();
1084  }
1085
1086
1087
1088  /**
1089   * Appends a string representation of the value for this ASN.1 element to the
1090   * provided buffer.
1091   *
1092   * @param  buffer  The buffer to which to append the information.
1093   */
1094  public void toString(final StringBuilder buffer)
1095  {
1096    final byte[] v = getValue();
1097    buffer.append("ASN1Element(type=");
1098    toHex(type, buffer);
1099    buffer.append(", valueLength=");
1100    buffer.append(v.length);
1101    buffer.append(", valueBytes='");
1102    toHex(v, buffer);
1103    buffer.append("')");
1104  }
1105}