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