1 package org.bouncycastle.asn1;
2
3 import java.io.*;
4 import java.util.*;
5
6 abstract public class ASN1Set
7 extends DERObject
8 {
9 protected Vector set = new Vector();
10
11 /**
12 * return an ASN1Set from the given object.
13 *
14 * @param obj the object we want converted.
15 * @exception IllegalArgumentException if the object cannot be converted.
16 */
17 public static ASN1Set getInstance(
18 Object obj)
19 {
20 if (obj == null || obj instanceof ASN1Set)
21 {
22 return (ASN1Set)obj;
23 }
24
25 throw new IllegalArgumentException("unknown object in getInstance");
26 }
27
28 /**
29 * Return an ASN1 set from a tagged object. There is a special
30 * case here, if an object appears to have been explicitly tagged on
31 * reading but we were expecting it to be implictly tagged in the
32 * normal course of events it indicates that we lost the surrounding
33 * set - so we need to add it back (this will happen if the tagged
34 * object is a sequence that contains other sequences). If you are
35 * dealing with implicitly tagged sets you really <b>should</b>
36 * be using this method.
37 *
38 * @param obj the tagged object.
39 * @param explicit true if the object is meant to be explicitly tagged
40 * false otherwise.
41 * @exception IllegalArgumentException if the tagged object cannot
42 * be converted.
43 */
44 public static ASN1Set getInstance(
45 ASN1TaggedObject obj,
46 boolean explicit)
47 {
48 if (explicit)
49 {
50 if (!obj.isExplicit())
51 {
52 throw new IllegalArgumentException("object implicit - explicit expected.");
53 }
54
55 return (ASN1Set)obj.getObject();
56 }
57 else
58 {
59 //
60 // constructed object which appears to be explicitly tagged
61 // and it's really implicit means we have to add the
62 // surrounding sequence.
63 //
64 if (obj.isExplicit())
65 {
66 ASN1Set set = new DERSet(obj.getObject());
67
68 return set;
69 }
70 else
71 {
72 //
73 // in this case the parser returns a sequence, convert it
74 // into a set.
75 //
76 DEREncodableVector v = new DEREncodableVector();
77
78 if (obj.getObject() instanceof ASN1Sequence)
79 {
80 ASN1Sequence s = (ASN1Sequence)obj.getObject();
81 Enumeration e = s.getObjects();
82
83 while (e.hasMoreElements())
84 {
85 v.add((DEREncodable)e.nextElement());
86 }
87
88 return new DERSet(v);
89 }
90 }
91 }
92
93 throw new IllegalArgumentException(
94 "unknown object in getInstanceFromTagged");
95 }
96
97 public ASN1Set()
98 {
99 }
100
101 public Enumeration getObjects()
102 {
103 return set.elements();
104 }
105
106 /**
107 * return the object at the set postion indicated by index.
108 *
109 * @param the set number (starting at zero) of the object
110 * @return the object at the set postion indicated by index.
111 */
112 public DEREncodable getObjectAt(
113 int index)
114 {
115 return (DEREncodable)set.elementAt(index);
116 }
117
118 /**
119 * return the number of objects in this set.
120 *
121 * @return the number of objects in this set.
122 */
123 public int size()
124 {
125 return set.size();
126 }
127
128 public int hashCode()
129 {
130 Enumeration e = this.getObjects();
131 int hashCode = 0;
132
133 while (e.hasMoreElements())
134 {
135 hashCode ^= e.nextElement().hashCode();
136 }
137
138 return hashCode;
139 }
140
141 public boolean equals(
142 Object o)
143 {
144 if (o == null || !(o instanceof ASN1Set))
145 {
146 return false;
147 }
148
149 ASN1Set other = (ASN1Set)o;
150
151 if (this.size() != other.size())
152 {
153 return false;
154 }
155
156 Enumeration s1 = this.getObjects();
157 Enumeration s2 = other.getObjects();
158
159 while (s1.hasMoreElements())
160 {
161 if (!s1.nextElement().equals(s2.nextElement()))
162 {
163 return false;
164 }
165 }
166
167 return true;
168 }
169
170 protected void addObject(
171 DEREncodable obj)
172 {
173 set.addElement(obj);
174 }
175
176 abstract void encode(DEROutputStream out)
177 throws IOException;
178 }
179