001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.crypto.asn1;
019
020 import java.io.IOException;
021 import java.util.Enumeration;
022 import java.util.Vector;
023
024 public abstract class ASN1Sequence
025 extends DERObject
026 {
027 private Vector seq = new Vector();
028
029 /**
030 * return an ASN1Sequence from the given object.
031 *
032 * @param obj the object we want converted.
033 * @exception IllegalArgumentException if the object cannot be converted.
034 */
035 public static ASN1Sequence getInstance(
036 Object obj)
037 {
038 if (obj == null || obj instanceof ASN1Sequence)
039 {
040 return (ASN1Sequence)obj;
041 }
042
043 throw new IllegalArgumentException("unknown object in getInstance");
044 }
045
046 /**
047 * Return an ASN1 sequence from a tagged object. There is a special
048 * case here, if an object appears to have been explicitly tagged on
049 * reading but we were expecting it to be implictly tagged in the
050 * normal course of events it indicates that we lost the surrounding
051 * sequence - so we need to add it back (this will happen if the tagged
052 * object is a sequence that contains other sequences). If you are
053 * dealing with implicitly tagged sequences you really <b>should</b>
054 * be using this method.
055 *
056 * @param obj the tagged object.
057 * @param explicit true if the object is meant to be explicitly tagged,
058 * false otherwise.
059 * @exception IllegalArgumentException if the tagged object cannot
060 * be converted.
061 */
062 public static ASN1Sequence getInstance(
063 ASN1TaggedObject obj,
064 boolean explicit)
065 {
066 if (explicit)
067 {
068 if (!obj.isExplicit())
069 {
070 throw new IllegalArgumentException("object implicit - explicit expected.");
071 }
072
073 return (ASN1Sequence)obj.getObject();
074 }
075 else
076 {
077 //
078 // constructed object which appears to be explicitly tagged
079 // when it should be implicit means we have to add the
080 // surrounding sequence.
081 //
082 if (obj.isExplicit())
083 {
084 if (obj instanceof BERTaggedObject)
085 {
086 return new BERSequence(obj.getObject());
087 }
088 else
089 {
090 return new DERSequence(obj.getObject());
091 }
092 }
093 else
094 {
095 if (obj.getObject() instanceof ASN1Sequence)
096 {
097 return (ASN1Sequence)obj.getObject();
098 }
099 }
100 }
101
102 throw new IllegalArgumentException(
103 "unknown object in getInstanceFromTagged");
104 }
105
106 public Enumeration getObjects()
107 {
108 return seq.elements();
109 }
110
111 /**
112 * return the object at the sequence postion indicated by index.
113 *
114 * @param index the sequence number (starting at zero) of the object
115 * @return the object at the sequence postion indicated by index.
116 */
117 public DEREncodable getObjectAt(
118 int index)
119 {
120 return (DEREncodable)seq.elementAt(index);
121 }
122
123 /**
124 * return the number of objects in this sequence.
125 *
126 * @return the number of objects in this sequence.
127 */
128 public int size()
129 {
130 return seq.size();
131 }
132
133 public int hashCode()
134 {
135 Enumeration e = this.getObjects();
136 int hashCode = 0;
137
138 while (e.hasMoreElements())
139 {
140 Object o = e.nextElement();
141
142 if (o != null)
143 {
144 hashCode ^= o.hashCode();
145 }
146 }
147
148 return hashCode;
149 }
150
151 public boolean equals(
152 Object o)
153 {
154 if (o == null || !(o instanceof ASN1Sequence))
155 {
156 return false;
157 }
158
159 ASN1Sequence other = (ASN1Sequence)o;
160
161 if (this.size() != other.size())
162 {
163 return false;
164 }
165
166 Enumeration s1 = this.getObjects();
167 Enumeration s2 = other.getObjects();
168
169 while (s1.hasMoreElements())
170 {
171 Object o1 = s1.nextElement();
172 Object o2 = s2.nextElement();
173
174 if (o1 != null && o2 != null)
175 {
176 if (!o1.equals(o2))
177 {
178 return false;
179 }
180 }
181 else if (o1 == null && o2 == null)
182 {
183 continue;
184 }
185 else
186 {
187 return false;
188 }
189 }
190
191 return true;
192 }
193
194 protected void addObject(
195 DEREncodable obj)
196 {
197 seq.addElement(obj);
198 }
199
200 abstract void encode(DEROutputStream out)
201 throws IOException;
202 }