001: package org.bouncycastle.asn1;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.IOException;
005: import java.util.Enumeration;
006: import java.util.Vector;
007:
008: abstract public class ASN1Set extends ASN1Object {
009: protected Vector set = new Vector();
010:
011: /**
012: * return an ASN1Set from the given object.
013: *
014: * @param obj the object we want converted.
015: * @exception IllegalArgumentException if the object cannot be converted.
016: */
017: public static ASN1Set getInstance(Object obj) {
018: if (obj == null || obj instanceof ASN1Set) {
019: return (ASN1Set) obj;
020: }
021:
022: throw new IllegalArgumentException(
023: "unknown object in getInstance");
024: }
025:
026: /**
027: * Return an ASN1 set from a tagged object. There is a special
028: * case here, if an object appears to have been explicitly tagged on
029: * reading but we were expecting it to be implictly tagged in the
030: * normal course of events it indicates that we lost the surrounding
031: * set - so we need to add it back (this will happen if the tagged
032: * object is a sequence that contains other sequences). If you are
033: * dealing with implicitly tagged sets you really <b>should</b>
034: * be using this method.
035: *
036: * @param obj the tagged object.
037: * @param explicit true if the object is meant to be explicitly tagged
038: * false otherwise.
039: * @exception IllegalArgumentException if the tagged object cannot
040: * be converted.
041: */
042: public static ASN1Set getInstance(ASN1TaggedObject obj,
043: boolean explicit) {
044: if (explicit) {
045: if (!obj.isExplicit()) {
046: throw new IllegalArgumentException(
047: "object implicit - explicit expected.");
048: }
049:
050: return (ASN1Set) obj.getObject();
051: } else {
052: //
053: // constructed object which appears to be explicitly tagged
054: // and it's really implicit means we have to add the
055: // surrounding sequence.
056: //
057: if (obj.isExplicit()) {
058: ASN1Set set = new DERSet(obj.getObject());
059:
060: return set;
061: } else {
062: if (obj.getObject() instanceof ASN1Set) {
063: return (ASN1Set) obj.getObject();
064: }
065:
066: //
067: // in this case the parser returns a sequence, convert it
068: // into a set.
069: //
070: ASN1EncodableVector v = new ASN1EncodableVector();
071:
072: if (obj.getObject() instanceof ASN1Sequence) {
073: ASN1Sequence s = (ASN1Sequence) obj.getObject();
074: Enumeration e = s.getObjects();
075:
076: while (e.hasMoreElements()) {
077: v.add((DEREncodable) e.nextElement());
078: }
079:
080: return new DERSet(v, false);
081: }
082: }
083: }
084:
085: throw new IllegalArgumentException(
086: "unknown object in getInstanceFromTagged");
087: }
088:
089: public ASN1Set() {
090: }
091:
092: public Enumeration getObjects() {
093: return set.elements();
094: }
095:
096: /**
097: * return the object at the set postion indicated by index.
098: *
099: * @param index the set number (starting at zero) of the object
100: * @return the object at the set postion indicated by index.
101: */
102: public DEREncodable getObjectAt(int index) {
103: return (DEREncodable) set.elementAt(index);
104: }
105:
106: /**
107: * return the number of objects in this set.
108: *
109: * @return the number of objects in this set.
110: */
111: public int size() {
112: return set.size();
113: }
114:
115: public ASN1SetParser parser() {
116: final ASN1Set outer = this ;
117:
118: return new ASN1SetParser() {
119: private final int max = size();
120:
121: private int index;
122:
123: public DEREncodable readObject() throws IOException {
124: if (index == max) {
125: return null;
126: }
127:
128: DEREncodable obj = getObjectAt(index++);
129: if (obj instanceof ASN1Sequence) {
130: return ((ASN1Sequence) obj).parser();
131: }
132: if (obj instanceof ASN1Set) {
133: return ((ASN1Set) obj).parser();
134: }
135:
136: return obj;
137: }
138:
139: public DERObject getDERObject() {
140: return outer;
141: }
142: };
143: }
144:
145: public int hashCode() {
146: Enumeration e = this .getObjects();
147: int hashCode = 0;
148:
149: while (e.hasMoreElements()) {
150: hashCode ^= e.nextElement().hashCode();
151: }
152:
153: return hashCode;
154: }
155:
156: boolean asn1Equals(DERObject o) {
157: if (!(o instanceof ASN1Set)) {
158: return false;
159: }
160:
161: ASN1Set other = (ASN1Set) o;
162:
163: if (this .size() != other.size()) {
164: return false;
165: }
166:
167: Enumeration s1 = this .getObjects();
168: Enumeration s2 = other.getObjects();
169:
170: while (s1.hasMoreElements()) {
171: DERObject o1 = ((DEREncodable) s1.nextElement())
172: .getDERObject();
173: DERObject o2 = ((DEREncodable) s2.nextElement())
174: .getDERObject();
175:
176: if (o1 == o2 || (o1 != null && o1.equals(o2))) {
177: continue;
178: }
179:
180: return false;
181: }
182:
183: return true;
184: }
185:
186: /**
187: * return true if a <= b (arrays are assumed padded with zeros).
188: */
189: private boolean lessThanOrEqual(byte[] a, byte[] b) {
190: if (a.length <= b.length) {
191: for (int i = 0; i != a.length; i++) {
192: int l = a[i] & 0xff;
193: int r = b[i] & 0xff;
194:
195: if (r > l) {
196: return true;
197: } else if (l > r) {
198: return false;
199: }
200: }
201:
202: return true;
203: } else {
204: for (int i = 0; i != b.length; i++) {
205: int l = a[i] & 0xff;
206: int r = b[i] & 0xff;
207:
208: if (r > l) {
209: return true;
210: } else if (l > r) {
211: return false;
212: }
213: }
214:
215: return false;
216: }
217: }
218:
219: private byte[] getEncoded(DEREncodable obj) {
220: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
221: ASN1OutputStream aOut = new ASN1OutputStream(bOut);
222:
223: try {
224: aOut.writeObject(obj);
225: } catch (IOException e) {
226: throw new IllegalArgumentException(
227: "cannot encode object added to SET");
228: }
229:
230: return bOut.toByteArray();
231: }
232:
233: protected void sort() {
234: if (set.size() > 1) {
235: boolean swapped = true;
236: int lastSwap = set.size() - 1;
237:
238: while (swapped) {
239: int index = 0;
240: int swapIndex = 0;
241: byte[] a = getEncoded((DEREncodable) set.elementAt(0));
242:
243: swapped = false;
244:
245: while (index != lastSwap) {
246: byte[] b = getEncoded((DEREncodable) set
247: .elementAt(index + 1));
248:
249: if (lessThanOrEqual(a, b)) {
250: a = b;
251: } else {
252: Object o = set.elementAt(index);
253:
254: set.setElementAt(set.elementAt(index + 1),
255: index);
256: set.setElementAt(o, index + 1);
257:
258: swapped = true;
259: swapIndex = index;
260: }
261:
262: index++;
263: }
264:
265: lastSwap = swapIndex;
266: }
267: }
268: }
269:
270: protected void addObject(DEREncodable obj) {
271: set.addElement(obj);
272: }
273:
274: abstract void encode(DEROutputStream out) throws IOException;
275:
276: public String toString() {
277: return set.toString();
278: }
279: }
|