1package org.bouncycastle.asn1; 2 3import java.io.IOException; 4import java.io.OutputStream; 5 6/** 7 * Stream that produces output based on the default encoding for the passed in objects. 8 */ 9public class ASN1OutputStream 10{ 11 private OutputStream os; 12 13 public ASN1OutputStream( 14 OutputStream os) 15 { 16 this.os = os; 17 } 18 19 void writeLength( 20 int length) 21 throws IOException 22 { 23 if (length > 127) 24 { 25 int size = 1; 26 int val = length; 27 28 while ((val >>>= 8) != 0) 29 { 30 size++; 31 } 32 33 write((byte)(size | 0x80)); 34 35 for (int i = (size - 1) * 8; i >= 0; i -= 8) 36 { 37 write((byte)(length >> i)); 38 } 39 } 40 else 41 { 42 write((byte)length); 43 } 44 } 45 46 void write(int b) 47 throws IOException 48 { 49 os.write(b); 50 } 51 52 void write(byte[] bytes) 53 throws IOException 54 { 55 os.write(bytes); 56 } 57 58 void write(byte[] bytes, int off, int len) 59 throws IOException 60 { 61 os.write(bytes, off, len); 62 } 63 64 void writeEncoded( 65 int tag, 66 byte[] bytes) 67 throws IOException 68 { 69 write(tag); 70 writeLength(bytes.length); 71 write(bytes); 72 } 73 74 void writeTag(int flags, int tagNo) 75 throws IOException 76 { 77 if (tagNo < 31) 78 { 79 write(flags | tagNo); 80 } 81 else 82 { 83 write(flags | 0x1f); 84 if (tagNo < 128) 85 { 86 write(tagNo); 87 } 88 else 89 { 90 byte[] stack = new byte[5]; 91 int pos = stack.length; 92 93 stack[--pos] = (byte)(tagNo & 0x7F); 94 95 do 96 { 97 tagNo >>= 7; 98 stack[--pos] = (byte)(tagNo & 0x7F | 0x80); 99 } 100 while (tagNo > 127); 101 102 write(stack, pos, stack.length - pos); 103 } 104 } 105 } 106 107 void writeEncoded(int flags, int tagNo, byte[] bytes) 108 throws IOException 109 { 110 writeTag(flags, tagNo); 111 writeLength(bytes.length); 112 write(bytes); 113 } 114 115 protected void writeNull() 116 throws IOException 117 { 118 os.write(BERTags.NULL); 119 os.write(0x00); 120 } 121 122 public void writeObject( 123 ASN1Encodable obj) 124 throws IOException 125 { 126 if (obj != null) 127 { 128 obj.toASN1Primitive().encode(this); 129 } 130 else 131 { 132 throw new IOException("null object detected"); 133 } 134 } 135 136 void writeImplicitObject(ASN1Primitive obj) 137 throws IOException 138 { 139 if (obj != null) 140 { 141 obj.encode(new ImplicitOutputStream(os)); 142 } 143 else 144 { 145 throw new IOException("null object detected"); 146 } 147 } 148 149 public void close() 150 throws IOException 151 { 152 os.close(); 153 } 154 155 public void flush() 156 throws IOException 157 { 158 os.flush(); 159 } 160 161 ASN1OutputStream getDERSubStream() 162 { 163 return new DEROutputStream(os); 164 } 165 166 ASN1OutputStream getDLSubStream() 167 { 168 return new DLOutputStream(os); 169 } 170 171 private class ImplicitOutputStream 172 extends ASN1OutputStream 173 { 174 private boolean first = true; 175 176 public ImplicitOutputStream(OutputStream os) 177 { 178 super(os); 179 } 180 181 public void write(int b) 182 throws IOException 183 { 184 if (first) 185 { 186 first = false; 187 } 188 else 189 { 190 super.write(b); 191 } 192 } 193 } 194} 195