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    }