1package org.bouncycastle.asn1;
2
3import java.io.ByteArrayOutputStream;
4import java.io.IOException;
5import java.util.Enumeration;
6import java.util.Vector;
7
8public class BERConstructedOctetString
9    extends DEROctetString
10{
11    private static final int MAX_LENGTH = 1000;
12
13    /**
14     * convert a vector of octet strings into a single byte string
15     */
16    static private byte[] toBytes(
17        Vector  octs)
18    {
19        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
20
21        for (int i = 0; i != octs.size(); i++)
22        {
23            try
24            {
25                DEROctetString  o = (DEROctetString)octs.elementAt(i);
26
27                bOut.write(o.getOctets());
28            }
29            catch (ClassCastException e)
30            {
31                throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
32            }
33            catch (IOException e)
34            {
35                throw new IllegalArgumentException("exception converting octets " + e.toString());
36            }
37        }
38
39        return bOut.toByteArray();
40    }
41
42    private Vector  octs;
43
44    /**
45     * @param string the octets making up the octet string.
46     */
47    public BERConstructedOctetString(
48        byte[]  string)
49    {
50        super(string);
51    }
52
53    public BERConstructedOctetString(
54        Vector  octs)
55    {
56        super(toBytes(octs));
57
58        this.octs = octs;
59    }
60
61    public BERConstructedOctetString(
62        DERObject  obj)
63    {
64        super(obj);
65    }
66
67    public BERConstructedOctetString(
68        DEREncodable  obj)
69    {
70        super(obj.getDERObject());
71    }
72
73    public byte[] getOctets()
74    {
75        return string;
76    }
77
78    /**
79     * return the DER octets that make up this string.
80     */
81    public Enumeration getObjects()
82    {
83        if (octs == null)
84        {
85            return generateOcts().elements();
86        }
87
88        return octs.elements();
89    }
90
91    private Vector generateOcts()
92    {
93        Vector vec = new Vector();
94        for (int i = 0; i < string.length; i += MAX_LENGTH)
95        {
96            int end;
97
98            if (i + MAX_LENGTH > string.length)
99            {
100                end = string.length;
101            }
102            else
103            {
104                end = i + MAX_LENGTH;
105            }
106
107            byte[] nStr = new byte[end - i];
108
109            System.arraycopy(string, i, nStr, 0, nStr.length);
110
111            vec.addElement(new DEROctetString(nStr));
112         }
113
114         return vec;
115    }
116
117    public void encode(
118        DEROutputStream out)
119        throws IOException
120    {
121        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
122        {
123            out.write(CONSTRUCTED | OCTET_STRING);
124
125            out.write(0x80);
126
127            //
128            // write out the octet array
129            //
130            Enumeration e = getObjects();
131            while (e.hasMoreElements())
132            {
133                out.writeObject(e.nextElement());
134            }
135
136            out.write(0x00);
137            out.write(0x00);
138        }
139        else
140        {
141            super.encode(out);
142        }
143    }
144
145    public static BERConstructedOctetString fromSequence(ASN1Sequence seq)
146    {
147        Vector      v = new Vector();
148        Enumeration e = seq.getObjects();
149
150        while (e.hasMoreElements())
151        {
152            v.addElement(e.nextElement());
153        }
154
155        return new BERConstructedOctetString(v);
156    }
157}
158