Home | History | Annotate | Download | only in asn1
      1 package org.bouncycastle.asn1;
      2 
      3 import java.io.IOException;
      4 
      5 /**
      6  * DER TaggedObject - in ASN.1 notation this is any object preceded by
      7  * a [n] where n is some number - these are assumed to follow the construction
      8  * rules (as with sequences).
      9  */
     10 public class DERTaggedObject
     11     extends ASN1TaggedObject
     12 {
     13     private static final byte[] ZERO_BYTES = new byte[0];
     14 
     15     /**
     16      * @param explicit true if an explicitly tagged object.
     17      * @param tagNo the tag number for this object.
     18      * @param obj the tagged object.
     19      */
     20     public DERTaggedObject(
     21         boolean       explicit,
     22         int           tagNo,
     23         ASN1Encodable obj)
     24     {
     25         super(explicit, tagNo, obj);
     26     }
     27 
     28     public DERTaggedObject(int tagNo, ASN1Encodable encodable)
     29     {
     30         super(true, tagNo, encodable);
     31     }
     32 
     33     boolean isConstructed()
     34     {
     35         if (!empty)
     36         {
     37             if (explicit)
     38             {
     39                 return true;
     40             }
     41             else
     42             {
     43                 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
     44 
     45                 return primitive.isConstructed();
     46             }
     47         }
     48         else
     49         {
     50             return true;
     51         }
     52     }
     53 
     54     int encodedLength()
     55         throws IOException
     56     {
     57         if (!empty)
     58         {
     59             ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
     60             int length = primitive.encodedLength();
     61 
     62             if (explicit)
     63             {
     64                 return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
     65             }
     66             else
     67             {
     68                 // header length already in calculation
     69                 length = length - 1;
     70 
     71                 return StreamUtil.calculateTagLength(tagNo) + length;
     72             }
     73         }
     74         else
     75         {
     76             return StreamUtil.calculateTagLength(tagNo) + 1;
     77         }
     78     }
     79 
     80     void encode(
     81         ASN1OutputStream out)
     82         throws IOException
     83     {
     84         if (!empty)
     85         {
     86             ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
     87 
     88             if (explicit)
     89             {
     90                 out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
     91                 out.writeLength(primitive.encodedLength());
     92                 out.writeObject(primitive);
     93             }
     94             else
     95             {
     96                 //
     97                 // need to mark constructed types...
     98                 //
     99                 int flags;
    100                 if (primitive.isConstructed())
    101                 {
    102                     flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
    103                 }
    104                 else
    105                 {
    106                     flags = BERTags.TAGGED;
    107                 }
    108 
    109                 out.writeTag(flags, tagNo);
    110                 out.writeImplicitObject(primitive);
    111             }
    112         }
    113         else
    114         {
    115             out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
    116         }
    117     }
    118 }
    119