    001package org.apache.commons.ssl.asn1;
    002
    003import java.io.ByteArrayOutputStream;
    004import java.io.IOException;
    005import java.util.Enumeration;
    006import java.util.Vector;
    007
    008public class BERConstructedOctetString
    009    extends DEROctetString {
    010    private static final int MAX_LENGTH = 1000;
    011
    012    /** convert a vector of octet strings into a single byte string */
    013    static private byte[] toBytes(
    014        Vector octs) {
    015        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    016
    017        for (int i = 0; i != octs.size(); i++) {
    018            try {
    019                DEROctetString o = (DEROctetString) octs.elementAt(i);
    020
    021                bOut.write(o.getOctets());
    022            }
    023            catch (ClassCastException e) {
    024                throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
    025            }
    026            catch (IOException e) {
    027                throw new IllegalArgumentException("exception converting octets " + e.toString());
    028            }
    029        }
    030
    031        return bOut.toByteArray();
    032    }
    033
    034    private Vector octs;
    035
    036    /** @param string the octets making up the octet string. */
    037    public BERConstructedOctetString(
    038        byte[] string) {
    039        super(string);
    040    }
    041
    042    public BERConstructedOctetString(
    043        Vector octs) {
    044        super(toBytes(octs));
    045
    046        this.octs = octs;
    047    }
    048
    049    public BERConstructedOctetString(
    050        DERObject obj) {
    051        super(obj);
    052    }
    053
    054    public BERConstructedOctetString(
    055        DEREncodable obj) {
    056        super(obj.getDERObject());
    057    }
    058
    059    public byte[] getOctets() {
    060        return string;
    061    }
    062
    063    /** return the DER octets that make up this string. */
    064    public Enumeration getObjects() {
    065        if (octs == null) {
    066            return generateOcts().elements();
    067        }
    068
    069        return octs.elements();
    070    }
    071
    072    private Vector generateOcts() {
    073        int start = 0;
    074        int end = 0;
    075        Vector vec = new Vector();
    076
    077        while ((end + 1) < string.length) {
    078            if (string[end] == 0 && string[end + 1] == 0) {
    079                byte[] nStr = new byte[end - start + 1];
    080
    081                System.arraycopy(string, start, nStr, 0, nStr.length);
    082
    083                vec.addElement(new DEROctetString(nStr));
    084                start = end + 1;
    085            }
    086            end++;
    087        }
    088
    089        byte[] nStr = new byte[string.length - start];
    090
    091        System.arraycopy(string, start, nStr, 0, nStr.length);
    092
    093        vec.addElement(new DEROctetString(nStr));
    094
    095        return vec;
    096    }
    097
    098    public void encode(
    099        DEROutputStream out)
    100        throws IOException {
    101        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
    102            out.write(CONSTRUCTED | OCTET_STRING);
    103
    104            out.write(0x80);
    105
    106            //
    107            // write out the octet array
    108            //
    109            if (octs != null) {
    110                for (int i = 0; i != octs.size(); i++) {
    111                    out.writeObject(octs.elementAt(i));
    112                }
    113            } else {
    114                for (int i = 0; i < string.length; i += MAX_LENGTH) {
    115                    int end;
    116
    117                    if (i + MAX_LENGTH > string.length) {
    118                        end = string.length;
    119                    } else {
    120                        end = i + MAX_LENGTH;
    121                    }
    122
    123                    byte[] nStr = new byte[end - i];
    124
    125                    System.arraycopy(string, i, nStr, 0, nStr.length);
    126
    127                    out.writeObject(new DEROctetString(nStr));
    128                }
    129            }
    130
    131            out.write(0x00);
    132            out.write(0x00);
    133        } else {
    134            super.encode(out);
    135        }
    136    }
    137}