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 }