1 package org.bouncycastle.asn1;
2
3 import java.io.*;
4 import java.util.*;
5
6 public abstract class ASN1Sequence
7 extends DERObject
8 {
9 private Vector seq = new Vector();
10
11 /**
12 * return an ASN1Sequence 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 ASN1Sequence getInstance(
18 Object obj)
19 {
20 if (obj == null || obj instanceof ASN1Sequence)
21 {
22 return (ASN1Sequence)obj;
23 }
24
25 throw new IllegalArgumentException("unknown object in getInstance");
26 }
27
28 /**
29 * Return an ASN1 sequence 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 * sequence - 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 sequences 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 ASN1Sequence 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 (ASN1Sequence)obj.getObject();
56 }
57 else
58 {
59 //
60 // constructed object which appears to be explicitly tagged
61 // when it should be implicit means we have to add the
62 // surrounding sequence.
63 //
64 if (obj.isExplicit())
65 {
66 ASN1Sequence seq;
67
68 if (obj instanceof BERTaggedObject)
69 {
70 seq = new BERConstructedSequence();
71 }
72 else
73 {
74 seq = new DERConstructedSequence();
75 }
76
77 seq.addObject(obj.getObject());
78
79 return seq;
80 }
81 else
82 {
83 ASN1Sequence seq;
84
85 if (obj.getObject() instanceof ASN1Sequence)
86 {
87 return (ASN1Sequence)obj.getObject();
88 }
89 }
90 }
91
92 throw new IllegalArgumentException(
93 "unknown object in getInstanceFromTagged");
94 }
95
96 public Enumeration getObjects()
97 {
98 return seq.elements();
99 }
100
101 /**
102 * return the object at the sequence postion indicated by index.
103 *
104 * @param the sequence number (starting at zero) of the object
105 * @return the object at the sequence postion indicated by index.
106 */
107 public DEREncodable getObjectAt(
108 int index)
109 {
110 return (DEREncodable)seq.elementAt(index);
111 }
112
113 /**
114 * return the number of objects in this sequence.
115 *
116 * @return the number of objects in this sequence.
117 */
118 public int size()
119 {
120 return seq.size();
121 }
122
123 public int hashCode()
124 {
125 Enumeration e = this.getObjects();
126 int hashCode = 0;
127
128 while (e.hasMoreElements())
129 {
130 hashCode ^= e.nextElement().hashCode();
131 }
132
133 return hashCode;
134 }
135
136 public boolean equals(
137 Object o)
138 {
139 if (o == null || !(o instanceof ASN1Sequence))
140 {
141 return false;
142 }
143
144 ASN1Sequence other = (ASN1Sequence)o;
145
146 if (this.size() != other.size())
147 {
148 return false;
149 }
150
151 Enumeration s1 = this.getObjects();
152 Enumeration s2 = other.getObjects();
153
154 while (s1.hasMoreElements())
155 {
156 if (!s1.nextElement().equals(s2.nextElement()))
157 {
158 return false;
159 }
160 }
161
162 return true;
163 }
164
165 protected void addObject(
166 DEREncodable obj)
167 {
168 seq.addElement(obj);
169 }
170
171 abstract void encode(DEROutputStream out)
172 throws IOException;
173 }
174