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