001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.IOException;
005    import java.util.Enumeration;
006    import java.util.Vector;
007    
008    public 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    }