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}