DERNumericString.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.asn1;
2
3import java.io.IOException;
4
5import org.bouncycastle.util.Arrays;
6import org.bouncycastle.util.Strings;
7
8/**
9 * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
10 */
11public class DERNumericString
12    extends ASN1Primitive
13    implements ASN1String
14{
15    private byte[]  string;
16
17    /**
18     * return a Numeric string from the passed in object
19     *
20     * @exception IllegalArgumentException if the object cannot be converted.
21     */
22    public static DERNumericString getInstance(
23        Object  obj)
24    {
25        if (obj == null || obj instanceof DERNumericString)
26        {
27            return (DERNumericString)obj;
28        }
29
30        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
31    }
32
33    /**
34     * return an Numeric String from a tagged object.
35     *
36     * @param obj the tagged object holding the object we want
37     * @param explicit true if the object is meant to be explicitly
38     *              tagged false otherwise.
39     * @exception IllegalArgumentException if the tagged object cannot
40     *               be converted.
41     */
42    public static DERNumericString getInstance(
43        ASN1TaggedObject obj,
44        boolean          explicit)
45    {
46        ASN1Primitive o = obj.getObject();
47
48        if (explicit || o instanceof DERNumericString)
49        {
50            return getInstance(o);
51        }
52        else
53        {
54            return new DERNumericString(ASN1OctetString.getInstance(o).getOctets());
55        }
56    }
57
58    /**
59     * basic constructor - with bytes.
60     */
61    DERNumericString(
62        byte[]   string)
63    {
64        this.string = string;
65    }
66
67    /**
68     * basic constructor -  without validation..
69     */
70    public DERNumericString(
71        String   string)
72    {
73        this(string, false);
74    }
75
76    /**
77     * Constructor with optional validation.
78     *
79     * @param string the base string to wrap.
80     * @param validate whether or not to check the string.
81     * @throws IllegalArgumentException if validate is true and the string
82     * contains characters that should not be in a NumericString.
83     */
84    public DERNumericString(
85        String   string,
86        boolean  validate)
87    {
88        if (validate && !isNumericString(string))
89        {
90            throw new IllegalArgumentException("string contains illegal characters");
91        }
92
93        this.string = Strings.toByteArray(string);
94    }
95
96    public String getString()
97    {
98        return Strings.fromByteArray(string);
99    }
100
101    public String toString()
102    {
103        return getString();
104    }
105
106    public byte[] getOctets()
107    {
108        return Arrays.clone(string);
109    }
110
111    boolean isConstructed()
112    {
113        return false;
114    }
115
116    int encodedLength()
117    {
118        return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
119    }
120
121    void encode(
122        ASN1OutputStream out)
123        throws IOException
124    {
125        out.writeEncoded(BERTags.NUMERIC_STRING, string);
126    }
127
128    public int hashCode()
129    {
130        return Arrays.hashCode(string);
131    }
132
133    boolean asn1Equals(
134        ASN1Primitive o)
135    {
136        if (!(o instanceof DERNumericString))
137        {
138            return false;
139        }
140
141        DERNumericString  s = (DERNumericString)o;
142
143        return Arrays.areEqual(string, s.string);
144    }
145
146    /**
147     * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
148     *
149     * @param str string to validate.
150     * @return true if numeric, fale otherwise.
151     */
152    public static boolean isNumericString(
153        String  str)
154    {
155        for (int i = str.length() - 1; i >= 0; i--)
156        {
157            char    ch = str.charAt(i);
158
159            if (ch > 0x007f)
160            {
161                return false;
162            }
163
164            if (('0' <= ch && ch <= '9') || ch == ' ')
165            {
166                continue;
167            }
168
169            return false;
170        }
171
172        return true;
173    }
174}
175