001package org.apache.commons.ssl.asn1;
002
003import org.apache.commons.ssl.util.Hex;
004
005import java.io.ByteArrayInputStream;
006import java.io.ByteArrayOutputStream;
007import java.io.IOException;
008import java.io.InputStream;
009import java.util.Enumeration;
010import java.util.Vector;
011
012public 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}