1
package org.bouncycastle.asn1;
3
import java.io.ByteArrayOutputStream;
4
import java.io.IOException;
5
import java.util.Enumeration;
6
import java.util.Vector;
8
abstract public class ASN1Set
11
protected Vector set = new Vector();
14
* return an ASN1Set from the given object.
16
* @param obj the object we want converted.
17
* @exception IllegalArgumentException if the object cannot be converted.
19
public static ASN1Set getInstance(
22
if (obj == null || obj instanceof ASN1Set)
27
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
31
* Return an ASN1 set from a tagged object. There is a special
32
* case here, if an object appears to have been explicitly tagged on
33
* reading but we were expecting it to be implicitly tagged in the
34
* normal course of events it indicates that we lost the surrounding
35
* set - so we need to add it back (this will happen if the tagged
36
* object is a sequence that contains other sequences). If you are
37
* dealing with implicitly tagged sets you really <b>should</b>
38
* be using this method.
40
* @param obj the tagged object.
41
* @param explicit true if the object is meant to be explicitly tagged
43
* @exception IllegalArgumentException if the tagged object cannot
46
public static ASN1Set getInstance(
52
if (!obj.isExplicit())
54
throw new IllegalArgumentException("object implicit - explicit expected.");
57
return (ASN1Set)obj.getObject();
62
// constructed object which appears to be explicitly tagged
63
// and it's really implicit means we have to add the
64
// surrounding sequence.
68
ASN1Set set = new DERSet(obj.getObject());
74
if (obj.getObject() instanceof ASN1Set)
76
return (ASN1Set)obj.getObject();
80
// in this case the parser returns a sequence, convert it
83
ASN1EncodableVector v = new ASN1EncodableVector();
85
if (obj.getObject() instanceof ASN1Sequence)
87
ASN1Sequence s = (ASN1Sequence)obj.getObject();
88
Enumeration e = s.getObjects();
90
while (e.hasMoreElements())
92
v.add((DEREncodable)e.nextElement());
95
return new DERSet(v, false);
100
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
107
public Enumeration getObjects()
109
return set.elements();
113
* return the object at the set position indicated by index.
115
* @param index the set number (starting at zero) of the object
116
* @return the object at the set position indicated by index.
118
public DEREncodable getObjectAt(
121
return (DEREncodable)set.elementAt(index);
125
* return the number of objects in this set.
127
* @return the number of objects in this set.
134
public ASN1Encodable[] toArray()
136
ASN1Encodable[] values = new ASN1Encodable[this.size()];
138
for (int i = 0; i != this.size(); i++)
140
values[i] = (ASN1Encodable)this.getObjectAt(i);
146
public ASN1SetParser parser()
148
final ASN1Set outer = this;
150
return new ASN1SetParser()
152
private final int max = size();
156
public DEREncodable readObject() throws IOException
163
DEREncodable obj = getObjectAt(index++);
164
if (obj instanceof ASN1Sequence)
166
return ((ASN1Sequence)obj).parser();
168
if (obj instanceof ASN1Set)
170
return ((ASN1Set)obj).parser();
176
public DERObject getLoadedObject()
181
public DERObject getDERObject()
188
public int hashCode()
190
Enumeration e = this.getObjects();
191
int hashCode = size();
193
while (e.hasMoreElements())
195
Object o = getNext(e);
198
hashCode ^= o.hashCode();
207
if (!(o instanceof ASN1Set))
212
ASN1Set other = (ASN1Set)o;
214
if (this.size() != other.size())
219
Enumeration s1 = this.getObjects();
220
Enumeration s2 = other.getObjects();
222
while (s1.hasMoreElements())
224
DEREncodable obj1 = getNext(s1);
225
DEREncodable obj2 = getNext(s2);
227
DERObject o1 = obj1.getDERObject();
228
DERObject o2 = obj2.getDERObject();
230
if (o1 == o2 || o1.equals(o2))
241
private DEREncodable getNext(Enumeration e)
243
DEREncodable encObj = (DEREncodable)e.nextElement();
245
// unfortunately null was allowed as a substitute for DER null
248
return DERNull.INSTANCE;
255
* return true if a <= b (arrays are assumed padded with zeros).
257
private boolean lessThanOrEqual(
261
int len = Math.min(a.length, b.length);
262
for (int i = 0; i != len; ++i)
266
return (a[i] & 0xff) < (b[i] & 0xff);
269
return len == a.length;
272
private byte[] getEncoded(
275
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
276
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
280
aOut.writeObject(obj);
282
catch (IOException e)
284
throw new IllegalArgumentException("cannot encode object added to SET");
287
return bOut.toByteArray();
290
protected void sort()
294
boolean swapped = true;
295
int lastSwap = set.size() - 1;
301
byte[] a = getEncoded((DEREncodable)set.elementAt(0));
305
while (index != lastSwap)
307
byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
309
if (lessThanOrEqual(a, b))
315
Object o = set.elementAt(index);
317
set.setElementAt(set.elementAt(index + 1), index);
318
set.setElementAt(o, index + 1);
327
lastSwap = swapIndex;
332
protected void addObject(
338
abstract void encode(DEROutputStream out)
341
public String toString()
343
return set.toString();