    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}