001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.IOException;
004
005import org.bouncycastle.util.Arrays;
006import org.bouncycastle.util.Strings;
007
008/**
009 * DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126.
010 * <p>
011 * Explicit character set escape sequences are not allowed.
012 * </p>
013 */
014public class DERVisibleString
015    extends ASN1Primitive
016    implements ASN1String
017{
018    private byte[]  string;
019
020    /**
021     * Return a Visible String from the passed in object.
022     *
023     * @param obj a DERVisibleString or an object that can be converted into one.
024     * @exception IllegalArgumentException if the object cannot be converted.
025     * @return a DERVisibleString instance, or null
026     */
027    public static DERVisibleString getInstance(
028        Object  obj)
029    {
030        if (obj == null || obj instanceof DERVisibleString)
031        {
032            return (DERVisibleString)obj;
033        }
034
035        if (obj instanceof byte[])
036        {
037            try
038            {
039                return (DERVisibleString)fromByteArray((byte[])obj);
040            }
041            catch (Exception e)
042            {
043                throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
044            }
045        }
046
047        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
048    }
049
050    /**
051     * Return a Visible String from a tagged object.
052     *
053     * @param obj the tagged object holding the object we want
054     * @param explicit true if the object is meant to be explicitly
055     *              tagged false otherwise.
056     * @exception IllegalArgumentException if the tagged object cannot
057     *               be converted.
058     * @return a DERVisibleString instance, or null
059     */
060    public static DERVisibleString getInstance(
061        ASN1TaggedObject obj,
062        boolean          explicit)
063    {
064        ASN1Primitive o = obj.getObject();
065
066        if (explicit || o instanceof DERVisibleString)
067        {
068            return getInstance(o);
069        }
070        else
071        {
072            return new DERVisibleString(ASN1OctetString.getInstance(o).getOctets());
073        }
074    }
075
076    /**
077     * Basic constructor - byte encoded string.
078     */
079    DERVisibleString(
080        byte[]   string)
081    {
082        this.string = string;
083    }
084
085    /**
086     * Basic constructor
087     */
088    public DERVisibleString(
089        String   string)
090    {
091        this.string = Strings.toByteArray(string);
092    }
093
094    public String getString()
095    {
096        return Strings.fromByteArray(string);
097    }
098
099    public String toString()
100    {
101        return getString();
102    }
103
104    public byte[] getOctets()
105    {
106        return Arrays.clone(string);
107    }
108
109    boolean isConstructed()
110    {
111        return false;
112    }
113
114    int encodedLength()
115    {
116        return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
117    }
118
119    void encode(
120        ASN1OutputStream out)
121        throws IOException
122    {
123        out.writeEncoded(BERTags.VISIBLE_STRING, this.string);
124    }
125    
126    boolean asn1Equals(
127        ASN1Primitive o)
128    {
129        if (!(o instanceof DERVisibleString))
130        {
131            return false;
132        }
133
134        return Arrays.areEqual(string, ((DERVisibleString)o).string);
135    }
136    
137    public int hashCode()
138    {
139        return Arrays.hashCode(string);
140    }
141}