001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import java.util.Enumeration;
004import java.util.Hashtable;
005import java.util.Vector;
006
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Encodable;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
013import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
014import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
015
016public class Extensions
017    extends ASN1Object
018{
019    private Hashtable extensions = new Hashtable();
020    private Vector ordering = new Vector();
021
022    public static Extensions getInstance(
023        ASN1TaggedObject obj,
024        boolean explicit)
025    {
026        return getInstance(ASN1Sequence.getInstance(obj, explicit));
027    }
028
029    public static Extensions getInstance(
030        Object obj)
031    {
032        if (obj instanceof Extensions)
033        {
034            return (Extensions)obj;
035        }
036        else if (obj != null)
037        {
038            return new Extensions(ASN1Sequence.getInstance(obj));
039        }
040
041        return null;
042    }
043
044    /**
045     * Constructor from ASN1Sequence.
046     * <p>
047     * The extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
048     * </p>
049     */
050    private Extensions(
051        ASN1Sequence seq)
052    {
053        Enumeration e = seq.getObjects();
054
055        while (e.hasMoreElements())
056        {
057            Extension ext = Extension.getInstance(e.nextElement());
058
059            extensions.put(ext.getExtnId(), ext);
060            ordering.addElement(ext.getExtnId());
061        }
062    }
063
064    /**
065     * Base Constructor
066     *
067     * @param extension a single extension.
068     */
069    public Extensions(
070        Extension extension)
071    {
072        this.ordering.addElement(extension.getExtnId());
073        this.extensions.put(extension.getExtnId(), extension);
074    }
075
076    /**
077     * Base Constructor
078     *
079     * @param extensions an array of extensions.
080     */
081    public Extensions(
082        Extension[] extensions)
083    {
084        for (int i = 0; i != extensions.length; i++)
085        {
086            Extension ext = extensions[i];
087
088            this.ordering.addElement(ext.getExtnId());
089            this.extensions.put(ext.getExtnId(), ext);
090        }
091    }
092
093    /**
094     * return an Enumeration of the extension field's object ids.
095     */
096    public Enumeration oids()
097    {
098        return ordering.elements();
099    }
100
101    /**
102     * return the extension represented by the object identifier
103     * passed in.
104     *
105     * @return the extension if it's present, null otherwise.
106     */
107    public Extension getExtension(
108        ASN1ObjectIdentifier oid)
109    {
110        return (Extension)extensions.get(oid);
111    }
112
113    /**
114     * return the parsed value of the extension represented by the object identifier
115     * passed in.
116     *
117     * @return the parsed value of the extension if it's present, null otherwise.
118     */
119    public ASN1Encodable getExtensionParsedValue(ASN1ObjectIdentifier oid)
120    {
121        Extension ext = this.getExtension(oid);
122
123        if (ext != null)
124        {
125            return ext.getParsedValue();
126        }
127
128        return null;
129    }
130
131    /**
132     * <pre>
133     *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
134     *
135     *     Extension         ::=   SEQUENCE {
136     *        extnId            EXTENSION.&amp;id ({ExtensionSet}),
137     *        critical          BOOLEAN DEFAULT FALSE,
138     *        extnValue         OCTET STRING }
139     * </pre>
140     */
141    public ASN1Primitive toASN1Primitive()
142    {
143        ASN1EncodableVector vec = new ASN1EncodableVector();
144        Enumeration e = ordering.elements();
145
146        while (e.hasMoreElements())
147        {
148            ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
149            Extension ext = (Extension)extensions.get(oid);
150
151            vec.add(ext);
152        }
153
154        return new DERSequence(vec);
155    }
156
157    public boolean equivalent(
158        Extensions other)
159    {
160        if (extensions.size() != other.extensions.size())
161        {
162            return false;
163        }
164
165        Enumeration e1 = extensions.keys();
166
167        while (e1.hasMoreElements())
168        {
169            Object key = e1.nextElement();
170
171            if (!extensions.get(key).equals(other.extensions.get(key)))
172            {
173                return false;
174            }
175        }
176
177        return true;
178    }
179
180    public ASN1ObjectIdentifier[] getExtensionOIDs()
181    {
182        return toOidArray(ordering);
183    }
184
185    public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
186    {
187        return getExtensionOIDs(false);
188    }
189
190    public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
191    {
192        return getExtensionOIDs(true);
193    }
194
195    private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
196    {
197        Vector oidVec = new Vector();
198
199        for (int i = 0; i != ordering.size(); i++)
200        {
201            Object oid = ordering.elementAt(i);
202
203            if (((Extension)extensions.get(oid)).isCritical() == isCritical)
204            {
205                oidVec.addElement(oid);
206            }
207        }
208
209        return toOidArray(oidVec);
210    }
211
212    private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
213    {
214        ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
215
216        for (int i = 0; i != oids.length; i++)
217        {
218            oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
219        }
220        return oids;
221    }
222}