001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004
005import org.bouncycastle.util.Arrays;
006
007/**
008 * Public facade of ASN.1 Boolean data.
009 * <p>
010 * Use following to place a new instance of ASN.1 Boolean in your dataset:
011 * </p>
012 * <ul>
013 * <li> ASN1Boolean.TRUE literal</li>
014 * <li> ASN1Boolean.FALSE literal</li>
015 * <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
016 * <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
017 * </ul>
018 * </p>
019 */
020public class ASN1Boolean
021    extends ASN1Primitive
022{
023    private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
024    private static final byte[] FALSE_VALUE = new byte[] { 0 };
025
026    private byte[]         value;
027
028    public static final ASN1Boolean FALSE = new ASN1Boolean(false);
029    public static final ASN1Boolean TRUE  = new ASN1Boolean(true);
030
031    /**
032     * return a boolean from the passed in object.
033     *
034     * @param obj an ASN1Boolean or an object that can be converted into one.
035     * @exception IllegalArgumentException if the object cannot be converted.
036     * @return an ASN1Boolean instance.
037     */
038    public static ASN1Boolean getInstance(
039        Object  obj)
040    {
041        if (obj == null || obj instanceof ASN1Boolean)
042        {
043            return (ASN1Boolean)obj;
044        }
045
046        if (obj instanceof byte[])
047        {
048            byte[] enc = (byte[])obj;
049            try
050            {
051                return (ASN1Boolean)fromByteArray(enc);
052            }
053            catch (IOException e)
054            {
055                throw new IllegalArgumentException("failed to construct boolean from byte[]: " + e.getMessage());
056            }
057        }
058
059        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
060    }
061
062    /**
063     * return an ASN1Boolean from the passed in boolean.
064     * @return an ASN1Boolean instance.
065     */
066    public static ASN1Boolean getInstance(
067        boolean  value)
068    {
069        return (value ? TRUE : FALSE);
070    }
071
072    /**
073     * return an ASN1Boolean from the passed in value.
074     * @return an ASN1Boolean instance.
075     */
076    public static ASN1Boolean getInstance(
077        int value)
078    {
079        return (value != 0 ? TRUE : FALSE);
080    }
081
082    /**
083     * return a Boolean from a tagged object.
084     *
085     * @param obj the tagged object holding the object we want
086     * @param explicit true if the object is meant to be explicitly
087     *              tagged false otherwise.
088     * @exception IllegalArgumentException if the tagged object cannot
089     *               be converted.
090     * @return an ASN1Boolean instance.
091     */
092    public static ASN1Boolean getInstance(
093        ASN1TaggedObject obj,
094        boolean          explicit)
095    {
096        ASN1Primitive o = obj.getObject();
097
098        if (explicit || o instanceof ASN1Boolean)
099        {
100            return getInstance(o);
101        }
102        else
103        {
104            return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
105        }
106    }
107
108    ASN1Boolean(
109        byte[] value)
110    {
111        if (value.length != 1)
112        {
113            throw new IllegalArgumentException("byte value should have 1 byte in it");
114        }
115
116        if (value[0] == 0)
117        {
118            this.value = FALSE_VALUE;
119        }
120        else if ((value[0] & 0xff) == 0xff)
121        {
122            this.value = TRUE_VALUE;
123        }
124        else
125        {
126            this.value = Arrays.clone(value);
127        }
128    }
129
130    /**
131     * @deprecated use getInstance(boolean) method.
132     * @param value true or false.
133     */
134    public ASN1Boolean(
135        boolean     value)
136    {
137        this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
138    }
139
140    public boolean isTrue()
141    {
142        return (value[0] != 0);
143    }
144
145    boolean isConstructed()
146    {
147        return false;
148    }
149
150    int encodedLength()
151    {
152        return 3;
153    }
154
155    void encode(
156        ASN1OutputStream out)
157        throws IOException
158    {
159        out.writeEncoded(BERTags.BOOLEAN, value);
160    }
161
162    protected boolean asn1Equals(
163        ASN1Primitive  o)
164    {
165        if (o instanceof ASN1Boolean)
166        {
167            return (value[0] == ((ASN1Boolean)o).value[0]);
168        }
169
170        return false;
171    }
172
173    public int hashCode()
174    {
175        return value[0];
176    }
177
178
179    public String toString()
180    {
181      return (value[0] != 0) ? "TRUE" : "FALSE";
182    }
183
184    static ASN1Boolean fromOctetString(byte[] value)
185    {
186        if (value.length != 1)
187        {
188            throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
189        }
190
191        if (value[0] == 0)
192        {
193            return FALSE;
194        }
195        else if ((value[0] & 0xff) == 0xff)
196        {
197            return TRUE;
198        }
199        else
200        {
201            return new ASN1Boolean(value);
202        }
203    }
204}