001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.crypto.asn1;
019    
020    import java.io.ByteArrayOutputStream;
021    import java.io.IOException;
022    import java.util.Enumeration;
023    import java.util.Vector;
024    
025    public class BERConstructedOctetString
026        extends DEROctetString
027    {
028        /**
029         * convert a vector of octet strings into a single byte string
030         */
031        static private byte[] toBytes(
032            Vector  octs)
033        {
034            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
035    
036            for (int i = 0; i != octs.size(); i++)
037            {
038                try
039                {
040                    DEROctetString  o = (DEROctetString)octs.elementAt(i);
041    
042                    bOut.write(o.getOctets());
043                }
044                catch (ClassCastException e)
045                {
046                    throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString", e);
047                }
048                catch (IOException e)
049                {
050                    throw new IllegalArgumentException("exception converting octets " + e.getMessage(), e);
051                }
052            }
053    
054            return bOut.toByteArray();
055        }
056    
057        private Vector  octs;
058    
059        /**
060         * @param string the octets making up the octet string.
061         */
062        public BERConstructedOctetString(
063            byte[]  string)
064        {
065            super(string);
066        }
067    
068        public BERConstructedOctetString(
069            Vector  octs)
070        {
071            super(toBytes(octs));
072    
073            this.octs = octs;
074        }
075    
076        public BERConstructedOctetString(
077            DERObject  obj)
078        {
079            super(obj);
080        }
081    
082        public BERConstructedOctetString(
083            DEREncodable  obj)
084        {
085            super(obj.getDERObject());
086        }
087    
088        public byte[] getOctets()
089        {
090            return string;
091        }
092    
093        /**
094         * return the DER octets that make up this string.
095         */
096        public Enumeration getObjects()
097        {
098            if (octs == null)
099            {
100                return generateOcts().elements();
101            }
102    
103            return octs.elements();
104        }
105    
106        private Vector generateOcts()
107        {
108            int     start = 0;
109            int     end = 0;
110            Vector  vec = new Vector();
111    
112            while ((end + 1) < string.length)
113            {
114                if (string[end] == 0 && string[end + 1] == 0)
115                {
116                    byte[]  nStr = new byte[end - start + 1];
117    
118                    System.arraycopy(string, start, nStr, 0, nStr.length);
119    
120                    vec.addElement(new DEROctetString(nStr));
121                    start = end + 1;
122                }
123                end++;
124            }
125    
126            byte[]  nStr = new byte[string.length - start];
127    
128            System.arraycopy(string, start, nStr, 0, nStr.length);
129    
130            vec.addElement(new DEROctetString(nStr));
131    
132            return vec;
133        }
134    
135        public void encode(
136            DEROutputStream out)
137            throws IOException
138        {
139            if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
140            {
141                out.write(CONSTRUCTED | OCTET_STRING);
142    
143                out.write(0x80);
144    
145                //
146                // write out the octet array
147                //
148                if (octs != null)
149                {
150                    for (int i = 0; i != octs.size(); i++)
151                    {
152                        out.writeObject(octs.elementAt(i));
153                    }
154                }
155                else
156                {
157                    int     start = 0;
158                    int     end = 0;
159    
160                    while ((end + 1) < string.length)
161                    {
162                        if (string[end] == 0 && string[end + 1] == 0)
163                        {
164                            byte[]  nStr = new byte[end - start + 1];
165    
166                            System.arraycopy(string, start, nStr, 0, nStr.length);
167    
168                            out.writeObject(new DEROctetString(nStr));
169                            start = end + 1;
170                        }
171                        end++;
172                    }
173    
174                    byte[]  nStr = new byte[string.length - start];
175    
176                    System.arraycopy(string, start, nStr, 0, nStr.length);
177    
178                    out.writeObject(new DEROctetString(nStr));
179                }
180    
181                out.write(0x00);
182                out.write(0x00);
183            }
184            else
185            {
186                super.encode(out);
187            }
188        }
189    }