001package org.apache.commons.ssl.org.bouncycastle.asn1; 002 003import java.io.IOException; 004import java.io.OutputStream; 005 006/** 007 * Stream that produces output based on the default encoding for the passed in objects. 008 */ 009public class ASN1OutputStream 010{ 011 private OutputStream os; 012 013 public ASN1OutputStream( 014 OutputStream os) 015 { 016 this.os = os; 017 } 018 019 void writeLength( 020 int length) 021 throws IOException 022 { 023 if (length > 127) 024 { 025 int size = 1; 026 int val = length; 027 028 while ((val >>>= 8) != 0) 029 { 030 size++; 031 } 032 033 write((byte)(size | 0x80)); 034 035 for (int i = (size - 1) * 8; i >= 0; i -= 8) 036 { 037 write((byte)(length >> i)); 038 } 039 } 040 else 041 { 042 write((byte)length); 043 } 044 } 045 046 void write(int b) 047 throws IOException 048 { 049 os.write(b); 050 } 051 052 void write(byte[] bytes) 053 throws IOException 054 { 055 os.write(bytes); 056 } 057 058 void write(byte[] bytes, int off, int len) 059 throws IOException 060 { 061 os.write(bytes, off, len); 062 } 063 064 void writeEncoded( 065 int tag, 066 byte[] bytes) 067 throws IOException 068 { 069 write(tag); 070 writeLength(bytes.length); 071 write(bytes); 072 } 073 074 void writeTag(int flags, int tagNo) 075 throws IOException 076 { 077 if (tagNo < 31) 078 { 079 write(flags | tagNo); 080 } 081 else 082 { 083 write(flags | 0x1f); 084 if (tagNo < 128) 085 { 086 write(tagNo); 087 } 088 else 089 { 090 byte[] stack = new byte[5]; 091 int pos = stack.length; 092 093 stack[--pos] = (byte)(tagNo & 0x7F); 094 095 do 096 { 097 tagNo >>= 7; 098 stack[--pos] = (byte)(tagNo & 0x7F | 0x80); 099 } 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}