001 package org.apache.commons.ssl.asn1;
002
003 import java.io.IOException;
004 import java.util.Enumeration;
005 import java.util.Vector;
006
007 public abstract class ASN1Sequence
008 extends ASN1Object {
009 private Vector seq = new Vector();
010
011 /**
012 * return an ASN1Sequence from the given object.
013 *
014 * @param obj the object we want converted.
015 * @throws IllegalArgumentException if the object cannot be converted.
016 */
017 public static ASN1Sequence getInstance(
018 Object obj) {
019 if (obj == null || obj instanceof ASN1Sequence) {
020 return (ASN1Sequence) obj;
021 }
022
023 throw new IllegalArgumentException("unknown object in getInstance");
024 }
025
026 /**
027 * Return an ASN1 sequence 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 * sequence - 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 sequences 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 * @throws IllegalArgumentException if the tagged object cannot
040 * be converted.
041 */
042 public static ASN1Sequence getInstance(
043 ASN1TaggedObject obj,
044 boolean explicit) {
045 if (explicit) {
046 if (!obj.isExplicit()) {
047 throw new IllegalArgumentException("object implicit - explicit expected.");
048 }
049
050 return (ASN1Sequence) obj.getObject();
051 } else {
052 //
053 // constructed object which appears to be explicitly tagged
054 // when it should be implicit means we have to add the
055 // surrounding sequence.
056 //
057 if (obj.isExplicit()) {
058 if (obj instanceof BERTaggedObject) {
059 return new BERSequence(obj.getObject());
060 } else {
061 return new DERSequence(obj.getObject());
062 }
063 } else {
064 if (obj.getObject() instanceof ASN1Sequence) {
065 return (ASN1Sequence) obj.getObject();
066 }
067 }
068 }
069
070 throw new IllegalArgumentException(
071 "unknown object in getInstanceFromTagged");
072 }
073
074 public Enumeration getObjects() {
075 return seq.elements();
076 }
077
078 public ASN1SequenceParser parser() {
079 final ASN1Sequence outer = this;
080
081 return new ASN1SequenceParser() {
082 private final int max = size();
083
084 private int index;
085
086 public DEREncodable readObject() throws IOException {
087 if (index == max) {
088 return null;
089 }
090
091 DEREncodable obj = getObjectAt(index++);
092 if (obj instanceof ASN1Sequence) {
093 return ((ASN1Sequence) obj).parser();
094 }
095 if (obj instanceof ASN1Set) {
096 return ((ASN1Set) obj).parser();
097 }
098
099 return obj;
100 }
101
102 public DERObject getDERObject() {
103 return outer;
104 }
105 };
106 }
107
108 /**
109 * return the object at the sequence postion indicated by index.
110 *
111 * @param index the sequence number (starting at zero) of the object
112 * @return the object at the sequence postion indicated by index.
113 */
114 public DEREncodable getObjectAt(
115 int index) {
116 return (DEREncodable) seq.elementAt(index);
117 }
118
119 /**
120 * return the number of objects in this sequence.
121 *
122 * @return the number of objects in this sequence.
123 */
124 public int size() {
125 return seq.size();
126 }
127
128 public int hashCode() {
129 Enumeration e = this.getObjects();
130 int hashCode = 0;
131
132 while (e.hasMoreElements()) {
133 Object o = e.nextElement();
134
135 if (o != null) {
136 hashCode ^= o.hashCode();
137 }
138 }
139
140 return hashCode;
141 }
142
143 boolean asn1Equals(
144 DERObject o) {
145 if (!(o instanceof ASN1Sequence)) {
146 return false;
147 }
148
149 ASN1Sequence other = (ASN1Sequence) o;
150
151 if (this.size() != other.size()) {
152 return false;
153 }
154
155 Enumeration s1 = this.getObjects();
156 Enumeration s2 = other.getObjects();
157
158 while (s1.hasMoreElements()) {
159 DERObject o1 = ((DEREncodable) s1.nextElement()).getDERObject();
160 DERObject o2 = ((DEREncodable) s2.nextElement()).getDERObject();
161
162 if (o1 == o2 || (o1 != null && o1.equals(o2))) {
163 continue;
164 }
165
166 return false;
167 }
168
169 return true;
170 }
171
172 protected void addObject(
173 DEREncodable obj) {
174 seq.addElement(obj);
175 }
176
177 abstract void encode(DEROutputStream out)
178 throws IOException;
179
180 public String toString() {
181 return seq.toString();
182 }
183 }