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 import org.apache.directory.shared.i18n.I18n;
032
033
034 public class BERConstructedOctetString extends DEROctetString
035 {
036 private Vector<DEREncodable> octets;
037
038
039 /**
040 * @param string
041 * the octets making up the octet string.
042 */
043 public BERConstructedOctetString(byte[] string)
044 {
045 super( string );
046 }
047
048
049 public BERConstructedOctetString(Vector<DEREncodable> octets)
050 {
051 super( toBytes( octets ) );
052
053 this.octets = octets;
054 }
055
056
057 /**
058 * Convert a vector of octet strings into a single byte string.
059 */
060 private static byte[] toBytes( Vector<DEREncodable> octs )
061 {
062 ByteArrayOutputStream baos = new ByteArrayOutputStream();
063
064 for ( int i = 0; i != octs.size(); i++ )
065 {
066 try
067 {
068 DEROctetString o = ( DEROctetString ) octs.elementAt( i );
069
070 baos.write( o.getOctets() );
071 }
072 catch ( ClassCastException e )
073 {
074 throw new IllegalArgumentException( I18n.err( I18n.ERR_00025, octs.elementAt( i ).getClass().getName() ) );
075 }
076 catch ( IOException e )
077 {
078 throw new IllegalArgumentException( I18n.err( I18n.ERR_00026, e.toString() ) );
079 }
080 }
081
082 return baos.toByteArray();
083 }
084
085
086 /**
087 * @return Enumeration the DER octets that make up this string.
088 */
089 public Enumeration<DEREncodable> getObjects()
090 {
091 if ( octets == null )
092 {
093 return generateOcts().elements();
094 }
095
096 return octets.elements();
097 }
098
099
100 private Vector<DEREncodable> generateOcts()
101 {
102 int start = 0;
103 int end = 0;
104 Vector<DEREncodable> vector = new Vector<DEREncodable>();
105
106 while ( ( end + 1 ) < value.length )
107 {
108 if ( value[end] == 0 && value[end + 1] == 0 )
109 {
110 byte[] nStr = new byte[end - start + 1];
111
112 System.arraycopy( value, start, nStr, 0, nStr.length );
113
114 vector.addElement( new DEROctetString( nStr ) );
115 start = end + 1;
116 }
117 end++;
118 }
119
120 byte[] nStr = new byte[value.length - start];
121
122 System.arraycopy( value, start, nStr, 0, nStr.length );
123
124 vector.addElement( new DEROctetString( nStr ) );
125
126 return vector;
127 }
128
129
130 public void encode( ASN1OutputStream out ) throws IOException
131 {
132 out.write( CONSTRUCTED | OCTET_STRING );
133
134 out.write( DERObject.TAGGED );
135
136 if ( octets != null )
137 {
138 for ( int i = 0; i != octets.size(); i++ )
139 {
140 out.writeObject( octets.elementAt( i ) );
141 }
142 }
143 else
144 {
145 int start = 0;
146 int end = 0;
147
148 while ( ( end + 1 ) < value.length )
149 {
150 if ( value[end] == 0 && value[end + 1] == 0 )
151 {
152 byte[] newString = new byte[end - start + 1];
153
154 System.arraycopy( value, start, newString, 0, newString.length );
155
156 out.writeObject( new DEROctetString( newString ) );
157 start = end + 1;
158 }
159 end++;
160 }
161
162 byte[] newString = new byte[value.length - start];
163
164 System.arraycopy( value, start, newString, 0, newString.length );
165
166 out.writeObject( new DEROctetString( newString ) );
167 }
168
169 out.write( TERMINATOR );
170 out.write( TERMINATOR );
171 }
172 }