001    package org.apache.commons.ssl.asn1;
002    
003    import org.apache.commons.ssl.util.Hex;
004    
005    import java.io.ByteArrayInputStream;
006    import java.io.ByteArrayOutputStream;
007    import java.io.IOException;
008    import java.io.InputStream;
009    import java.util.Enumeration;
010    import java.util.Vector;
011    
012    public abstract class ASN1OctetString
013        extends ASN1Object
014        implements ASN1OctetStringParser {
015        byte[] string;
016    
017        /**
018         * return an Octet String from a tagged object.
019         *
020         * @param obj      the tagged object holding the object we want.
021         * @param explicit true if the object is meant to be explicitly
022         *                 tagged false otherwise.
023         * @throws IllegalArgumentException if the tagged object cannot
024         *                                  be converted.
025         */
026        public static ASN1OctetString getInstance(
027            ASN1TaggedObject obj,
028            boolean explicit) {
029            return getInstance(obj.getObject());
030        }
031    
032        /**
033         * return an Octet String from the given object.
034         *
035         * @param obj the object we want converted.
036         * @throws IllegalArgumentException if the object cannot be converted.
037         */
038        public static ASN1OctetString getInstance(
039            Object obj) {
040            if (obj == null || obj instanceof ASN1OctetString) {
041                return (ASN1OctetString) obj;
042            }
043    
044            if (obj instanceof ASN1TaggedObject) {
045                return getInstance(((ASN1TaggedObject) obj).getObject());
046            }
047    
048            if (obj instanceof ASN1Sequence) {
049                Vector v = new Vector();
050                Enumeration e = ((ASN1Sequence) obj).getObjects();
051    
052                while (e.hasMoreElements()) {
053                    v.addElement(e.nextElement());
054                }
055    
056                return new BERConstructedOctetString(v);
057            }
058    
059            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
060        }
061    
062        /** @param string the octets making up the octet string. */
063        public ASN1OctetString(
064            byte[] string) {
065            this.string = string;
066        }
067    
068        public ASN1OctetString(
069            DEREncodable obj) {
070            try {
071                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
072                DEROutputStream dOut = new DEROutputStream(bOut);
073    
074                dOut.writeObject(obj);
075                dOut.close();
076    
077                this.string = bOut.toByteArray();
078            }
079            catch (IOException e) {
080                throw new IllegalArgumentException("Error processing object : " + e.toString());
081            }
082        }
083    
084        public InputStream getOctetStream() {
085            return new ByteArrayInputStream(string);
086        }
087    
088        public ASN1OctetStringParser parser() {
089            return this;
090        }
091    
092        public byte[] getOctets() {
093            return string;
094        }
095    
096        public int hashCode() {
097            byte[] b = this.getOctets();
098            int value = 0;
099    
100            for (int i = 0; i != b.length; i++) {
101                value ^= (b[i] & 0xff) << (i % 4);
102            }
103    
104            return value;
105        }
106    
107        boolean asn1Equals(
108            DERObject o) {
109            if (!(o instanceof ASN1OctetString)) {
110                return false;
111            }
112    
113            ASN1OctetString other = (ASN1OctetString) o;
114    
115            byte[] b1 = other.string;
116            byte[] b2 = this.string;
117    
118            if (b1.length != b2.length) {
119                return false;
120            }
121    
122            for (int i = 0; i != b1.length; i++) {
123                if (b1[i] != b2[i]) {
124                    return false;
125                }
126            }
127    
128            return true;
129        }
130    
131        abstract void encode(DEROutputStream out)
132            throws IOException;
133    
134        public String toString() {
135            return "#" + Hex.encode(string);
136        }
137    }