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    
022    /**
023     * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
024     * a [n] where n is some number - these are assume to follow the construction
025     * rules (as with sequences).
026     */
027    public abstract class ASN1TaggedObject
028        extends DERObject
029    {
030        int             tagNo;
031        boolean         empty = false;
032        boolean         explicit = true;
033        DEREncodable    obj = null;
034    
035        static public ASN1TaggedObject getInstance(
036            ASN1TaggedObject    obj,
037            boolean             explicit)
038        {
039            if (explicit)
040            {
041                return (ASN1TaggedObject)obj.getObject();
042            }
043    
044            throw new IllegalArgumentException("implicitly tagged tagged object");
045        }
046    
047        /**
048         * Create a tagged object in the explicit style.
049         *
050         * @param tagNo the tag number for this object.
051         * @param obj the tagged object.
052         */
053        public ASN1TaggedObject(
054            int             tagNo,
055            DEREncodable    obj)
056        {
057            this.explicit = true;
058            this.tagNo = tagNo;
059            this.obj = obj;
060        }
061    
062        /**
063         * Create a tagged object with the style given by the value of explicit.
064         * <p>
065         * If the object implements ASN1Choice the tag style will always be changed
066         * to explicit in accordance with the ASN.1 encoding rules.
067         * </p>
068         * @param explicit true if the object is explicitly tagged.
069         * @param tagNo the tag number for this object.
070         * @param obj the tagged object.
071         */
072        public ASN1TaggedObject(
073            boolean         explicit,
074            int             tagNo,
075            DEREncodable    obj)
076        {
077            if (obj instanceof ASN1Choice)
078            {
079                this.explicit = true;
080            }
081            else
082            {
083                this.explicit = explicit;
084            }
085    
086            this.tagNo = tagNo;
087            this.obj = obj;
088        }
089    
090        public boolean equals(
091            Object o)
092        {
093            if (o == null || !(o instanceof ASN1TaggedObject))
094            {
095                return false;
096            }
097    
098            ASN1TaggedObject other = (ASN1TaggedObject)o;
099    
100            if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
101            {
102                return false;
103            }
104    
105            if(obj == null)
106            {
107                if(other.obj != null)
108                {
109                    return false;
110                }
111            }
112            else
113            {
114                if(!(obj.equals(other.obj)))
115                {
116                    return false;
117                }
118            }
119    
120            return true;
121        }
122    
123        public int hashCode()
124        {
125            int code = tagNo;
126    
127            if (obj != null)
128            {
129                code ^= obj.hashCode();
130            }
131    
132            return code;
133        }
134    
135        public int getTagNo()
136        {
137            return tagNo;
138        }
139    
140        /**
141         * return whether or not the object may be explicitly tagged.
142         * <p>
143         * Note: if the object has been read from an input stream, the only
144         * time you can be sure if isExplicit is returning the true state of
145         * affairs is if it returns false. An implicitly tagged object may appear
146         * to be explicitly tagged, so you need to understand the context under
147         * which the reading was done as well, see getObject below.
148         */
149        public boolean isExplicit()
150        {
151            return explicit;
152        }
153    
154        public boolean isEmpty()
155        {
156            return empty;
157        }
158    
159        /**
160         * return whatever was following the tag.
161         * <p>
162         * Note: tagged objects are generally context dependent if you're
163         * trying to extract a tagged object you should be going via the
164         * appropriate getInstance method.
165         */
166        public DERObject getObject()
167        {
168            if (obj != null)
169            {
170                return obj.getDERObject();
171            }
172    
173            return null;
174        }
175    
176        abstract void encode(DEROutputStream  out)
177            throws IOException;
178    }