1package org.bouncycastle.asn1;
2
3import java.io.ByteArrayOutputStream;
4import java.io.IOException;
5
6/**
7 * An indefinite-length encoding version of an application specific object.
8 */
9public class BERApplicationSpecific
10    extends ASN1ApplicationSpecific
11{
12    BERApplicationSpecific(
13        boolean isConstructed,
14        int tag,
15        byte[] octets)
16    {
17        super(isConstructed, tag, octets);
18    }
19
20    /**
21     * Create an application specific object with a tagging of explicit/constructed.
22     *
23     * @param tag the tag number for this object.
24     * @param object the object to be contained.
25     */
26    public BERApplicationSpecific(
27        int tag,
28        ASN1Encodable object)
29        throws IOException
30    {
31        this(true, tag, object);
32    }
33
34    /**
35     * Create an application specific object with the tagging style given by the value of constructed.
36     *
37     * @param constructed true if the object is constructed.
38     * @param tag the tag number for this object.
39     * @param object the object to be contained.
40     */
41    public BERApplicationSpecific(
42        boolean constructed,
43        int tag,
44        ASN1Encodable object)
45        throws IOException
46    {
47        super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object));
48    }
49
50    private static byte[] getEncoding(boolean explicit, ASN1Encodable object)
51        throws IOException
52    {
53        byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.BER);
54
55        if (explicit)
56        {
57            return data;
58        }
59        else
60        {
61            int lenBytes = getLengthOfHeader(data);
62            byte[] tmp = new byte[data.length - lenBytes];
63            System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
64            return tmp;
65        }
66    }
67
68    /**
69     * Create an application specific object which is marked as constructed
70     *
71     * @param tagNo the tag number for this object.
72     * @param vec the objects making up the application specific object.
73     */
74    public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
75    {
76        super(true, tagNo, getEncodedVector(vec));
77    }
78
79    private static byte[] getEncodedVector(ASN1EncodableVector vec)
80    {
81        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
82
83        for (int i = 0; i != vec.size(); i++)
84        {
85            try
86            {
87                bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.BER));
88            }
89            catch (IOException e)
90            {
91                throw new ASN1ParsingException("malformed object: " + e, e);
92            }
93        }
94        return bOut.toByteArray();
95    }
96
97    /* (non-Javadoc)
98     * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
99     */
100    void encode(ASN1OutputStream out) throws IOException
101    {
102        int classBits = BERTags.APPLICATION;
103        if (isConstructed)
104        {
105            classBits |= BERTags.CONSTRUCTED;
106        }
107
108        out.writeTag(classBits, tag);
109        out.write(0x80);
110        out.write(octets);
111        out.write(0x00);
112        out.write(0x00);
113    }
114}
115