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 }