• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.asn1;
2 
3 import java.io.IOException;
4 import java.util.Enumeration;
5 import java.util.Vector;
6 
7 public abstract class ASN1Sequence
8     extends ASN1Object
9 {
10     private Vector seq = new Vector();
11 
12     /**
13      * return an ASN1Sequence from the given object.
14      *
15      * @param obj the object we want converted.
16      * @exception IllegalArgumentException if the object cannot be converted.
17      */
getInstance( Object obj)18     public static ASN1Sequence getInstance(
19         Object  obj)
20     {
21         if (obj == null || obj instanceof ASN1Sequence)
22         {
23             return (ASN1Sequence)obj;
24         }
25         else if (obj instanceof byte[])
26         {
27             try
28             {
29                 return ASN1Sequence.getInstance(ASN1Object.fromByteArray((byte[])obj));
30             }
31             catch (IOException e)
32             {
33                 throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
34             }
35         }
36 
37         throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
38     }
39 
40     /**
41      * Return an ASN1 sequence from a tagged object. There is a special
42      * case here, if an object appears to have been explicitly tagged on
43      * reading but we were expecting it to be implicitly tagged in the
44      * normal course of events it indicates that we lost the surrounding
45      * sequence - so we need to add it back (this will happen if the tagged
46      * object is a sequence that contains other sequences). If you are
47      * dealing with implicitly tagged sequences you really <b>should</b>
48      * be using this method.
49      *
50      * @param obj the tagged object.
51      * @param explicit true if the object is meant to be explicitly tagged,
52      *          false otherwise.
53      * @exception IllegalArgumentException if the tagged object cannot
54      *          be converted.
55      */
getInstance( ASN1TaggedObject obj, boolean explicit)56     public static ASN1Sequence getInstance(
57         ASN1TaggedObject    obj,
58         boolean             explicit)
59     {
60         if (explicit)
61         {
62             if (!obj.isExplicit())
63             {
64                 throw new IllegalArgumentException("object implicit - explicit expected.");
65             }
66 
67             return (ASN1Sequence)obj.getObject();
68         }
69         else
70         {
71             //
72             // constructed object which appears to be explicitly tagged
73             // when it should be implicit means we have to add the
74             // surrounding sequence.
75             //
76             if (obj.isExplicit())
77             {
78                 if (obj instanceof BERTaggedObject)
79                 {
80                     return new BERSequence(obj.getObject());
81                 }
82                 else
83                 {
84                     return new DERSequence(obj.getObject());
85                 }
86             }
87             else
88             {
89                 if (obj.getObject() instanceof ASN1Sequence)
90                 {
91                     return (ASN1Sequence)obj.getObject();
92                 }
93             }
94         }
95 
96         throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
97     }
98 
getObjects()99     public Enumeration getObjects()
100     {
101         return seq.elements();
102     }
103 
parser()104     public ASN1SequenceParser parser()
105     {
106         final ASN1Sequence outer = this;
107 
108         return new ASN1SequenceParser()
109         {
110             private final int max = size();
111 
112             private int index;
113 
114             public DEREncodable readObject() throws IOException
115             {
116                 if (index == max)
117                 {
118                     return null;
119                 }
120 
121                 DEREncodable obj = getObjectAt(index++);
122                 if (obj instanceof ASN1Sequence)
123                 {
124                     return ((ASN1Sequence)obj).parser();
125                 }
126                 if (obj instanceof ASN1Set)
127                 {
128                     return ((ASN1Set)obj).parser();
129                 }
130 
131                 return obj;
132             }
133 
134             public DERObject getLoadedObject()
135             {
136                 return outer;
137             }
138 
139             public DERObject getDERObject()
140             {
141                 return outer;
142             }
143         };
144     }
145 
146     /**
147      * return the object at the sequence position indicated by index.
148      *
149      * @param index the sequence number (starting at zero) of the object
150      * @return the object at the sequence position indicated by index.
151      */
getObjectAt( int index)152     public DEREncodable getObjectAt(
153         int index)
154     {
155         return (DEREncodable)seq.elementAt(index);
156     }
157 
158     /**
159      * return the number of objects in this sequence.
160      *
161      * @return the number of objects in this sequence.
162      */
size()163     public int size()
164     {
165         return seq.size();
166     }
167 
hashCode()168     public int hashCode()
169     {
170         Enumeration             e = this.getObjects();
171         int                     hashCode = size();
172 
173         while (e.hasMoreElements())
174         {
175             Object o = getNext(e);
176             hashCode *= 17;
177 
178             hashCode ^= o.hashCode();
179         }
180 
181         return hashCode;
182     }
183 
asn1Equals( DERObject o)184     boolean asn1Equals(
185         DERObject  o)
186     {
187         if (!(o instanceof ASN1Sequence))
188         {
189             return false;
190         }
191 
192         ASN1Sequence   other = (ASN1Sequence)o;
193 
194         if (this.size() != other.size())
195         {
196             return false;
197         }
198 
199         Enumeration s1 = this.getObjects();
200         Enumeration s2 = other.getObjects();
201 
202         while (s1.hasMoreElements())
203         {
204             DEREncodable  obj1 = getNext(s1);
205             DEREncodable  obj2 = getNext(s2);
206 
207             DERObject  o1 = obj1.getDERObject();
208             DERObject  o2 = obj2.getDERObject();
209 
210             if (o1 == o2 || o1.equals(o2))
211             {
212                 continue;
213             }
214 
215             return false;
216         }
217 
218         return true;
219     }
220 
getNext(Enumeration e)221     private DEREncodable getNext(Enumeration e)
222     {
223         DEREncodable encObj = (DEREncodable)e.nextElement();
224 
225         // unfortunately null was allowed as a substitute for DER null
226         if (encObj == null)
227         {
228             return DERNull.INSTANCE;
229         }
230 
231         return encObj;
232     }
233 
addObject( DEREncodable obj)234     protected void addObject(
235         DEREncodable obj)
236     {
237         seq.addElement(obj);
238     }
239 
encode(DEROutputStream out)240     abstract void encode(DEROutputStream out)
241         throws IOException;
242 
toString()243     public String toString()
244     {
245       return seq.toString();
246     }
247 }
248