001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004
005/**
006 * Definite Length TaggedObject - in ASN.1 notation this is any object preceded by
007 * a [n] where n is some number - these are assumed to follow the construction
008 * rules (as with sequences).
009 */
010public class DLTaggedObject
011    extends ASN1TaggedObject
012{
013    private static final byte[] ZERO_BYTES = new byte[0];
014
015    /**
016     * @param explicit true if an explicitly tagged object.
017     * @param tagNo the tag number for this object.
018     * @param obj the tagged object.
019     */
020    public DLTaggedObject(
021        boolean explicit,
022        int tagNo,
023        ASN1Encodable obj)
024    {
025        super(explicit, tagNo, obj);
026    }
027
028    boolean isConstructed()
029    {
030        if (!empty)
031        {
032            if (explicit)
033            {
034                return true;
035            }
036            else
037            {
038                ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
039
040                return primitive.isConstructed();
041            }
042        }
043        else
044        {
045            return true;
046        }
047    }
048
049    int encodedLength()
050        throws IOException
051    {
052        if (!empty)
053        {
054            int length = obj.toASN1Primitive().toDLObject().encodedLength();
055
056            if (explicit)
057            {
058                return  StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
059            }
060            else
061            {
062                // header length already in calculation
063                length = length - 1;
064
065                return StreamUtil.calculateTagLength(tagNo) + length;
066            }
067        }
068        else
069        {
070            return StreamUtil.calculateTagLength(tagNo) + 1;
071        }
072    }
073
074    void encode(
075        ASN1OutputStream out)
076        throws IOException
077    {
078        if (!empty)
079        {
080            ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
081
082            if (explicit)
083            {
084                out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
085                out.writeLength(primitive.encodedLength());
086                out.writeObject(primitive);
087            }
088            else
089            {
090                //
091                // need to mark constructed types...
092                //
093                int flags;
094                if (primitive.isConstructed())
095                {
096                    flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
097                }
098                else
099                {
100                    flags = BERTags.TAGGED;
101                }
102
103                out.writeTag(flags, tagNo);
104                out.writeImplicitObject(primitive);
105            }
106        }
107        else
108        {
109            out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
110        }
111    }
112}