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 }