001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.IOException;
004    
005    /** DER IA5String object - this is an ascii string. */
006    public class DERIA5String
007        extends ASN1Object
008        implements DERString {
009        String string;
010    
011        /**
012         * return a IA5 string from the passed in object
013         *
014         * @throws IllegalArgumentException if the object cannot be converted.
015         */
016        public static DERIA5String getInstance(
017            Object obj) {
018            if (obj == null || obj instanceof DERIA5String) {
019                return (DERIA5String) obj;
020            }
021    
022            if (obj instanceof ASN1OctetString) {
023                return new DERIA5String(((ASN1OctetString) obj).getOctets());
024            }
025    
026            if (obj instanceof ASN1TaggedObject) {
027                return getInstance(((ASN1TaggedObject) obj).getObject());
028            }
029    
030            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
031        }
032    
033        /**
034         * return an IA5 String from a tagged object.
035         *
036         * @param obj      the tagged object holding the object we want
037         * @param explicit true if the object is meant to be explicitly
038         *                 tagged false otherwise.
039         * @throws IllegalArgumentException if the tagged object cannot
040         *                                  be converted.
041         */
042        public static DERIA5String getInstance(
043            ASN1TaggedObject obj,
044            boolean explicit) {
045            return getInstance(obj.getObject());
046        }
047    
048        /** basic constructor - with bytes. */
049        public DERIA5String(
050            byte[] string) {
051            char[] cs = new char[string.length];
052    
053            for (int i = 0; i != cs.length; i++) {
054                cs[i] = (char) (string[i] & 0xff);
055            }
056    
057            this.string = new String(cs);
058        }
059    
060        /** basic constructor - without validation. */
061        public DERIA5String(
062            String string) {
063            this(string, false);
064        }
065    
066        /**
067         * Constructor with optional validation.
068         *
069         * @param string   the base string to wrap.
070         * @param validate whether or not to check the string.
071         * @throws IllegalArgumentException if validate is true and the string
072         *                                  contains characters that should not be in an IA5String.
073         */
074        public DERIA5String(
075            String string,
076            boolean validate) {
077            if (validate && !isIA5String(string)) {
078                throw new IllegalArgumentException("string contains illegal characters");
079            }
080    
081            this.string = string;
082        }
083    
084        public String getString() {
085            return string;
086        }
087    
088        public String toString() {
089            return string;
090        }
091    
092        public byte[] getOctets() {
093            char[] cs = string.toCharArray();
094            byte[] bs = new byte[cs.length];
095    
096            for (int i = 0; i != cs.length; i++) {
097                bs[i] = (byte) cs[i];
098            }
099    
100            return bs;
101        }
102    
103        void encode(
104            DEROutputStream out)
105            throws IOException {
106            out.writeEncoded(IA5_STRING, this.getOctets());
107        }
108    
109        public int hashCode() {
110            return this.getString().hashCode();
111        }
112    
113        boolean asn1Equals(
114            DERObject o) {
115            if (!(o instanceof DERIA5String)) {
116                return false;
117            }
118    
119            DERIA5String s = (DERIA5String) o;
120    
121            return this.getString().equals(s.getString());
122        }
123    
124        /**
125         * return true if the passed in String can be represented without
126         * loss as an IA5String, false otherwise.
127         *
128         * @return true if in printable set, false otherwise.
129         */
130        public static boolean isIA5String(
131            String str) {
132            for (int i = str.length() - 1; i >= 0; i--) {
133                char ch = str.charAt(i);
134    
135                if (ch > 0x007f) {
136                    return false;
137                }
138            }
139    
140            return true;
141        }
142    }