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.util.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    }