ASN1Set.java revision db9f6e2562dff550a3c62aeb7c96e72fc40d1a06
1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.io.ByteArrayOutputStream;
4c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.io.IOException;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
6db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstromimport java.util.Vector;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamabstract public class ASN1Set
9db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    extends ASN1Object
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
11db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    protected Vector set = new Vector();
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * return an ASN1Set from the given object.
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param obj the object we want converted.
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception IllegalArgumentException if the object cannot be converted.
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static ASN1Set getInstance(
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Object  obj)
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (obj == null || obj instanceof ASN1Set)
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return (ASN1Set)obj;
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
27c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Return an ASN1 set from a tagged object. There is a special
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * case here, if an object appears to have been explicitly tagged on
33c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * reading but we were expecting it to be implicitly tagged in the
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * normal course of events it indicates that we lost the surrounding
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * set - so we need to add it back (this will happen if the tagged
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * object is a sequence that contains other sequences). If you are
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * dealing with implicitly tagged sets you really <b>should</b>
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * be using this method.
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param obj the tagged object.
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param explicit true if the object is meant to be explicitly tagged
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *          false otherwise.
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception IllegalArgumentException if the tagged object cannot
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *          be converted.
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static ASN1Set getInstance(
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1TaggedObject    obj,
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean             explicit)
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (explicit)
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (!obj.isExplicit())
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new IllegalArgumentException("object implicit - explicit expected.");
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return (ASN1Set)obj.getObject();
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // constructed object which appears to be explicitly tagged
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // and it's really implicit means we have to add the
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            // surrounding sequence.
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            //
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (obj.isExplicit())
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1Set    set = new DERSet(obj.getObject());
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return set;
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (obj.getObject() instanceof ASN1Set)
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    return (ASN1Set)obj.getObject();
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // in this case the parser returns a sequence, convert it
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                // into a set.
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                //
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1EncodableVector  v = new ASN1EncodableVector();
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (obj.getObject() instanceof ASN1Sequence)
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    ASN1Sequence s = (ASN1Sequence)obj.getObject();
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    Enumeration e = s.getObjects();
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    while (e.hasMoreElements())
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        v.add((DEREncodable)e.nextElement());
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    return new DERSet(v, false);
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
100c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public ASN1Set()
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
107db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    public Enumeration getObjects()
108db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
109db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        return set.elements();
110db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
111db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
112db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    /**
113db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * return the object at the set position indicated by index.
114db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     *
115db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * @param index the set number (starting at zero) of the object
116db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * @return the object at the set position indicated by index.
117db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     */
118db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    public DEREncodable getObjectAt(
119db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        int index)
120db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
121db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        return (DEREncodable)set.elementAt(index);
122db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
123db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
124db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    /**
125db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * return the number of objects in this set.
126db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     *
127db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * @return the number of objects in this set.
128db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     */
129db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    public int size()
130db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
131db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        return set.size();
132db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    public ASN1Encodable[] toArray()
1356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
1366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        ASN1Encodable[] values = new ASN1Encodable[this.size()];
1376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = 0; i != this.size(); i++)
1396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
1406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            values[i] = (ASN1Encodable)this.getObjectAt(i);
1416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
1426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
1436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return values;
1446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
1456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
146c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public ASN1SetParser parser()
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
148c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        final ASN1Set outer = this;
149c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
150c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return new ASN1SetParser()
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
152c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            private final int max = size();
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
154c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            private int index;
155c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
156c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            public DEREncodable readObject() throws IOException
157c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
158c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (index == max)
159c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
160c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    return null;
161c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
162c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
163c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                DEREncodable obj = getObjectAt(index++);
164c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (obj instanceof ASN1Sequence)
165c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
166c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    return ((ASN1Sequence)obj).parser();
167c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
168c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (obj instanceof ASN1Set)
169c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
170c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    return ((ASN1Set)obj).parser();
171c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
172c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
173c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return obj;
174c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
175c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            public DERObject getLoadedObject()
1776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
1786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                return outer;
1796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
1806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            public DERObject getDERObject()
182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                return outer;
184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        };
186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
188db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    public int hashCode()
189db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
190db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        Enumeration             e = this.getObjects();
191db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        int                     hashCode = size();
192db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
193db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        while (e.hasMoreElements())
194db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        {
195db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            Object o = getNext(e);
196db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            hashCode *= 17;
197db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
198db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            hashCode ^= o.hashCode();
199db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        }
200db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
201db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        return hashCode;
202db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
203c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
204c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    boolean asn1Equals(
205c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        DERObject  o)
206c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
207c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (!(o instanceof ASN1Set))
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return false;
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
212c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ASN1Set   other = (ASN1Set)o;
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (this.size() != other.size())
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return false;
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration s1 = this.getObjects();
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Enumeration s2 = other.getObjects();
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (s1.hasMoreElements())
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
2246e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            DEREncodable  obj1 = getNext(s1);
2256e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            DEREncodable  obj2 = getNext(s2);
2266e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2276e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            DERObject  o1 = obj1.getDERObject();
2286e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            DERObject  o2 = obj2.getDERObject();
229c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
2306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            if (o1 == o2 || o1.equals(o2))
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
232c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                continue;
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
234c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return false;
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return true;
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
2416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    private DEREncodable getNext(Enumeration e)
2426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
2436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        DEREncodable encObj = (DEREncodable)e.nextElement();
2446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        // unfortunately null was allowed as a substitute for DER null
2466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (encObj == null)
2476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
2486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            return DERNull.INSTANCE;
2496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
2506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
2516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return encObj;
2526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
2536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
254db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    /**
255db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     * return true if a <= b (arrays are assumed padded with zeros).
256db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom     */
257db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    private boolean lessThanOrEqual(
258db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom         byte[] a,
259db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom         byte[] b)
260db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
261db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        int len = Math.min(a.length, b.length);
262db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        for (int i = 0; i != len; ++i)
263db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        {
264db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            if (a[i] != b[i])
265db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            {
266db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                return (a[i] & 0xff) < (b[i] & 0xff);
267db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            }
268db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        }
269db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        return len == a.length;
270db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private byte[] getEncoded(
273c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        DEREncodable obj)
274c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
275c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
276c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
277c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
278c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        try
279c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
280c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            aOut.writeObject(obj);
281c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
282c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        catch (IOException e)
283c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
284c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            throw new IllegalArgumentException("cannot encode object added to SET");
285c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
286c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
287c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return bOut.toByteArray();
288c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
289c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
290db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    protected void sort()
291db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
292db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        if (set.size() > 1)
293db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        {
294db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            boolean    swapped = true;
295db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            int        lastSwap = set.size() - 1;
296db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
297db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            while (swapped)
298db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            {
299db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                int    index = 0;
300db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                int    swapIndex = 0;
301db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                byte[] a = getEncoded((DEREncodable)set.elementAt(0));
302db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
303db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                swapped = false;
304db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
305db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                while (index != lastSwap)
306db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                {
307db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
308db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
309db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    if (lessThanOrEqual(a, b))
310db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    {
311db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        a = b;
312db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    }
313db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    else
314db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    {
315db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        Object  o = set.elementAt(index);
316db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
317db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        set.setElementAt(set.elementAt(index + 1), index);
318db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        set.setElementAt(o, index + 1);
319db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
320db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        swapped = true;
321db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                        swapIndex = index;
322db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    }
323db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
324db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                    index++;
325db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                }
326db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
327db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom                lastSwap = swapIndex;
328db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            }
329db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        }
330db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
331db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
332db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    protected void addObject(
333db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        DEREncodable obj)
334db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
335db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom        set.addElement(obj);
336db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
337db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
338db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    abstract void encode(DEROutputStream out)
339db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom            throws IOException;
340db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom
341db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    public String toString()
342db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    {
343db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom      return set.toString();
344db9f6e2562dff550a3c62aeb7c96e72fc40d1a06Brian Carlstrom    }
345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
346