001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004import java.math.BigInteger;
005
006import org.bouncycastle.util.Arrays;
007
008/**
009 * Class representing the ASN.1 ENUMERATED type.
010 */
011public class ASN1Enumerated
012    extends ASN1Primitive
013{
014    byte[]      bytes;
015
016    /**
017     * return an enumerated from the passed in object
018     *
019     * @param obj an ASN1Enumerated or an object that can be converted into one.
020     * @exception IllegalArgumentException if the object cannot be converted.
021     * @return an ASN1Enumerated instance, or null.
022     */
023    public static ASN1Enumerated getInstance(
024        Object  obj)
025    {
026        if (obj == null || obj instanceof ASN1Enumerated)
027        {
028            return (ASN1Enumerated)obj;
029        }
030
031        if (obj instanceof byte[])
032        {
033            try
034            {
035                return (ASN1Enumerated)fromByteArray((byte[])obj);
036            }
037            catch (Exception e)
038            {
039                throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
040            }
041        }
042
043        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
044    }
045
046    /**
047     * return an Enumerated from a tagged object.
048     *
049     * @param obj the tagged object holding the object we want
050     * @param explicit true if the object is meant to be explicitly
051     *              tagged false otherwise.
052     * @exception IllegalArgumentException if the tagged object cannot
053     *               be converted.
054     * @return an ASN1Enumerated instance, or null.
055     */
056    public static ASN1Enumerated getInstance(
057        ASN1TaggedObject obj,
058        boolean          explicit)
059    {
060        ASN1Primitive o = obj.getObject();
061
062        if (explicit || o instanceof ASN1Enumerated)
063        {
064            return getInstance(o);
065        }
066        else
067        {
068            return fromOctetString(((ASN1OctetString)o).getOctets());
069        }
070    }
071
072    /**
073     * Constructor from int.
074     *
075     * @param value the value of this enumerated.
076     */
077    public ASN1Enumerated(
078        int         value)
079    {
080        bytes = BigInteger.valueOf(value).toByteArray();
081    }
082
083    /**
084     * Constructor from BigInteger
085     *
086     * @param value the value of this enumerated.
087     */
088    public ASN1Enumerated(
089        BigInteger   value)
090    {
091        bytes = value.toByteArray();
092    }
093
094    /**
095     * Constructor from encoded BigInteger.
096     *
097     * @param bytes the value of this enumerated as an encoded BigInteger (signed).
098     */
099    public ASN1Enumerated(
100        byte[]   bytes)
101    {
102        this.bytes = bytes;
103    }
104
105    public BigInteger getValue()
106    {
107        return new BigInteger(bytes);
108    }
109
110    boolean isConstructed()
111    {
112        return false;
113    }
114
115    int encodedLength()
116    {
117        return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
118    }
119
120    void encode(
121        ASN1OutputStream out)
122        throws IOException
123    {
124        out.writeEncoded(BERTags.ENUMERATED, bytes);
125    }
126    
127    boolean asn1Equals(
128        ASN1Primitive  o)
129    {
130        if (!(o instanceof ASN1Enumerated))
131        {
132            return false;
133        }
134
135        ASN1Enumerated other = (ASN1Enumerated)o;
136
137        return Arrays.areEqual(this.bytes, other.bytes);
138    }
139
140    public int hashCode()
141    {
142        return Arrays.hashCode(bytes);
143    }
144
145    private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
146
147    static ASN1Enumerated fromOctetString(byte[] enc)
148    {
149        if (enc.length > 1)
150        {
151            return new ASN1Enumerated(Arrays.clone(enc));
152        }
153
154        if (enc.length == 0)
155        {
156            throw new IllegalArgumentException("ENUMERATED has zero length");
157        }
158        int value = enc[0] & 0xff;
159
160        if (value >= cache.length)
161        {
162            return new ASN1Enumerated(Arrays.clone(enc));
163        }
164
165        ASN1Enumerated possibleMatch = cache[value];
166
167        if (possibleMatch == null)
168        {
169            possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
170        }
171
172        return possibleMatch;
173    }
174}