001 /*
002 * Copyright (c) 2000 - 2006 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
005 * software and associated documentation files (the "Software"), to deal in the Software
006 * without restriction, including without limitation the rights to use, copy, modify,
007 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
008 * permit persons to whom the Software is furnished to do so, subject to the following
009 * conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in all copies
012 * or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
015 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
016 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
017 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
018 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
019 * DEALINGS IN THE SOFTWARE.
020 *
021 */
022
023 package org.apache.directory.shared.asn1.der;
024
025
026 import java.io.ByteArrayOutputStream;
027 import java.io.IOException;
028 import java.util.Enumeration;
029 import java.util.Vector;
030
031
032 public class BERConstructedOctetString extends DEROctetString
033 {
034 private Vector<DEREncodable> octets;
035
036
037 /**
038 * @param string
039 * the octets making up the octet string.
040 */
041 public BERConstructedOctetString(byte[] string)
042 {
043 super( string );
044 }
045
046
047 public BERConstructedOctetString(Vector<DEREncodable> octets)
048 {
049 super( toBytes( octets ) );
050
051 this.octets = octets;
052 }
053
054
055 /**
056 * Convert a vector of octet strings into a single byte string.
057 */
058 private static byte[] toBytes( Vector<DEREncodable> octs )
059 {
060 ByteArrayOutputStream baos = new ByteArrayOutputStream();
061
062 for ( int i = 0; i != octs.size(); i++ )
063 {
064 try
065 {
066 DEROctetString o = ( DEROctetString ) octs.elementAt( i );
067
068 baos.write( o.getOctets() );
069 }
070 catch ( ClassCastException e )
071 {
072 throw new IllegalArgumentException( octs.elementAt( i ).getClass().getName()
073 + " found in input should only contain DEROctetString." );
074 }
075 catch ( IOException e )
076 {
077 throw new IllegalArgumentException( "Exception converting octets " + e.toString() );
078 }
079 }
080
081 return baos.toByteArray();
082 }
083
084
085 /**
086 * @return Enumeration the DER octets that make up this string.
087 */
088 public Enumeration<DEREncodable> getObjects()
089 {
090 if ( octets == null )
091 {
092 return generateOcts().elements();
093 }
094
095 return octets.elements();
096 }
097
098
099 private Vector<DEREncodable> generateOcts()
100 {
101 int start = 0;
102 int end = 0;
103 Vector<DEREncodable> vector = new Vector<DEREncodable>();
104
105 while ( ( end + 1 ) < value.length )
106 {
107 if ( value[end] == 0 && value[end + 1] == 0 )
108 {
109 byte[] nStr = new byte[end - start + 1];
110
111 System.arraycopy( value, start, nStr, 0, nStr.length );
112
113 vector.addElement( new DEROctetString( nStr ) );
114 start = end + 1;
115 }
116 end++;
117 }
118
119 byte[] nStr = new byte[value.length - start];
120
121 System.arraycopy( value, start, nStr, 0, nStr.length );
122
123 vector.addElement( new DEROctetString( nStr ) );
124
125 return vector;
126 }
127
128
129 public void encode( ASN1OutputStream out ) throws IOException
130 {
131 out.write( CONSTRUCTED | OCTET_STRING );
132
133 out.write( DERObject.TAGGED );
134
135 if ( octets != null )
136 {
137 for ( int i = 0; i != octets.size(); i++ )
138 {
139 out.writeObject( octets.elementAt( i ) );
140 }
141 }
142 else
143 {
144 int start = 0;
145 int end = 0;
146
147 while ( ( end + 1 ) < value.length )
148 {
149 if ( value[end] == 0 && value[end + 1] == 0 )
150 {
151 byte[] newString = new byte[end - start + 1];
152
153 System.arraycopy( value, start, newString, 0, newString.length );
154
155 out.writeObject( new DEROctetString( newString ) );
156 start = end + 1;
157 }
158 end++;
159 }
160
161 byte[] newString = new byte[value.length - start];
162
163 System.arraycopy( value, start, newString, 0, newString.length );
164
165 out.writeObject( new DEROctetString( newString ) );
166 }
167
168 out.write( TERMINATOR );
169 out.write( TERMINATOR );
170 }
171 }