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