001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.ByteArrayOutputStream;
004import java.io.IOException;
005import java.util.Enumeration;
006import java.util.Vector;
007
008public class BEROctetString
009    extends ASN1OctetString
010{
011    private static final int MAX_LENGTH = 1000;
012
013    private ASN1OctetString[] octs;
014
015    /**
016     * convert a vector of octet strings into a single byte string
017     */
018    static private byte[] toBytes(
019        ASN1OctetString[]  octs)
020    {
021        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
022
023        for (int i = 0; i != octs.length; i++)
024        {
025            try
026            {
027                DEROctetString o = (DEROctetString)octs[i];
028
029                bOut.write(o.getOctets());
030            }
031            catch (ClassCastException e)
032            {
033                throw new IllegalArgumentException(octs[i].getClass().getName() + " found in input should only contain DEROctetString");
034            }
035            catch (IOException e)
036            {
037                throw new IllegalArgumentException("exception converting octets " + e.toString());
038            }
039        }
040
041        return bOut.toByteArray();
042    }
043
044    /**
045     * @param string the octets making up the octet string.
046     */
047    public BEROctetString(
048        byte[] string)
049    {
050        super(string);
051    }
052
053    public BEROctetString(
054        ASN1OctetString[] octs)
055    {
056        super(toBytes(octs));
057
058        this.octs = octs;
059    }
060
061    public byte[] getOctets()
062    {
063        return string;
064    }
065
066    /**
067     * return the DER octets that make up this string.
068     */
069    public Enumeration getObjects()
070    {
071        if (octs == null)
072        {
073            return generateOcts().elements();
074        }
075
076        return new Enumeration()
077        {
078            int counter = 0;
079
080            public boolean hasMoreElements()
081            {
082                return counter < octs.length;
083            }
084
085            public Object nextElement()
086            {
087                return octs[counter++];
088            }
089        };
090    }
091
092    private Vector generateOcts()
093    { 
094        Vector vec = new Vector();
095        for (int i = 0; i < string.length; i += MAX_LENGTH) 
096        { 
097            int end; 
098
099            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}