001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004
005import org.bouncycastle.util.Arrays;
006
007/**
008 * DER BMPString object.
009 */
010public class DERBMPString
011    extends ASN1Primitive
012    implements ASN1String
013{
014    private char[]  string;
015
016    /**
017     * return a BMP String from the given object.
018     *
019     * @param obj the object we want converted.
020     * @exception IllegalArgumentException if the object cannot be converted.
021     * @return a DERBMPString instance, or null.
022     */
023    public static DERBMPString getInstance(
024        Object  obj)
025    {
026        if (obj == null || obj instanceof DERBMPString)
027        {
028            return (DERBMPString)obj;
029        }
030
031        if (obj instanceof byte[])
032        {
033            try
034            {
035                return (DERBMPString)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 a BMP String 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 a DERBMPString instance.
055     */
056    public static DERBMPString getInstance(
057        ASN1TaggedObject obj,
058        boolean          explicit)
059    {
060        ASN1Primitive o = obj.getObject();
061
062        if (explicit || o instanceof DERBMPString)
063        {
064            return getInstance(o);
065        }
066        else
067        {
068            return new DERBMPString(ASN1OctetString.getInstance(o).getOctets());
069        }
070    }
071
072    /**
073     * basic constructor - byte encoded string.
074     * @param string the encoded BMP STRING to wrap.
075     */
076    DERBMPString(
077        byte[]   string)
078    {
079        char[]  cs = new char[string.length / 2];
080
081        for (int i = 0; i != cs.length; i++)
082        {
083            cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
084        }
085
086        this.string = cs;
087    }
088
089    DERBMPString(char[] string)
090    {
091        this.string = string;
092    }
093
094    /**
095     * basic constructor
096     * @param string a String to wrap as a BMP STRING.
097     */
098    public DERBMPString(
099        String   string)
100    {
101        this.string = string.toCharArray();
102    }
103
104    public String getString()
105    {
106        return new String(string);
107    }
108
109    public String toString()
110    {
111        return getString();
112    }
113
114    public int hashCode()
115    {
116        return Arrays.hashCode(string);
117    }
118
119    protected boolean asn1Equals(
120        ASN1Primitive o)
121    {
122        if (!(o instanceof DERBMPString))
123        {
124            return false;
125        }
126
127        DERBMPString  s = (DERBMPString)o;
128
129        return Arrays.areEqual(string, s.string);
130    }
131
132    boolean isConstructed()
133    {
134        return false;
135    }
136
137    int encodedLength()
138    {
139        return 1 + StreamUtil.calculateBodyLength(string.length * 2) + (string.length * 2);
140    }
141
142    void encode(
143        ASN1OutputStream out)
144        throws IOException
145    {
146        out.write(BERTags.BMP_STRING);
147        out.writeLength(string.length * 2);
148
149        for (int i = 0; i != string.length; i++)
150        {
151            char c = string[i];
152
153            out.write((byte)(c >> 8));
154            out.write((byte)c);
155        }
156    }
157}