1package org.bouncycastle.asn1;
2
3import java.io.IOException;
4import java.util.Enumeration;
5
6/**
7 * A DER encoded SET object
8 */
9public class DERSet
10    extends ASN1Set
11{
12    private int bodyLength = -1;
13
14    /**
15     * create an empty set
16     */
17    public DERSet()
18    {
19    }
20
21    /**
22     * create a set containing one object
23     * @param obj the object to go in the set
24     */
25    public DERSet(
26        ASN1Encodable obj)
27    {
28        super(obj);
29    }
30
31    /**
32     * create a set containing a vector of objects.
33     * @param v the vector of objects to make up the set.
34     */
35    public DERSet(
36        ASN1EncodableVector v)
37    {
38        super(v, true);
39    }
40
41    /**
42     * create a set containing an array of objects.
43     * @param a the array of objects to make up the set.
44     */
45    public DERSet(
46        ASN1Encodable[]   a)
47    {
48        super(a, true);
49    }
50
51    DERSet(
52        ASN1EncodableVector v,
53        boolean                  doSort)
54    {
55        super(v, doSort);
56    }
57
58    private int getBodyLength()
59        throws IOException
60    {
61        if (bodyLength < 0)
62        {
63            int length = 0;
64
65            for (Enumeration e = this.getObjects(); e.hasMoreElements();)
66            {
67                Object    obj = e.nextElement();
68
69                length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
70            }
71
72            bodyLength = length;
73        }
74
75        return bodyLength;
76    }
77
78    int encodedLength()
79        throws IOException
80    {
81        int length = getBodyLength();
82
83        return 1 + StreamUtil.calculateBodyLength(length) + length;
84    }
85
86    /*
87     * A note on the implementation:
88     * <p>
89     * As DER requires the constructed, definite-length model to
90     * be used for structured types, this varies slightly from the
91     * ASN.1 descriptions given. Rather than just outputting SET,
92     * we also have to specify CONSTRUCTED, and the objects length.
93     */
94    void encode(
95        ASN1OutputStream out)
96        throws IOException
97    {
98        ASN1OutputStream        dOut = out.getDERSubStream();
99        int                     length = getBodyLength();
100
101        out.write(BERTags.SET | BERTags.CONSTRUCTED);
102        out.writeLength(length);
103
104        for (Enumeration e = this.getObjects(); e.hasMoreElements();)
105        {
106            Object    obj = e.nextElement();
107
108            dOut.writeObject((ASN1Encodable)obj);
109        }
110    }
111}
112