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