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