001package org.apache.commons.ssl.org.bouncycastle.asn1; 002 003import java.io.IOException; 004 005/** 006 * DER TaggedObject - in ASN.1 notation this is any object preceded by 007 * a [n] where n is some number - these are assumed to follow the construction 008 * rules (as with sequences). 009 */ 010public class DERTaggedObject 011 extends ASN1TaggedObject 012{ 013 private static final byte[] ZERO_BYTES = new byte[0]; 014 015 /** 016 * @param explicit true if an explicitly tagged object. 017 * @param tagNo the tag number for this object. 018 * @param obj the tagged object. 019 */ 020 public DERTaggedObject( 021 boolean explicit, 022 int tagNo, 023 ASN1Encodable obj) 024 { 025 super(explicit, tagNo, obj); 026 } 027 028 public DERTaggedObject(int tagNo, ASN1Encodable encodable) 029 { 030 super(true, tagNo, encodable); 031 } 032 033 boolean isConstructed() 034 { 035 if (!empty) 036 { 037 if (explicit) 038 { 039 return true; 040 } 041 else 042 { 043 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 044 045 return primitive.isConstructed(); 046 } 047 } 048 else 049 { 050 return true; 051 } 052 } 053 054 int encodedLength() 055 throws IOException 056 { 057 if (!empty) 058 { 059 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 060 int length = primitive.encodedLength(); 061 062 if (explicit) 063 { 064 return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length; 065 } 066 else 067 { 068 // header length already in calculation 069 length = length - 1; 070 071 return StreamUtil.calculateTagLength(tagNo) + length; 072 } 073 } 074 else 075 { 076 return StreamUtil.calculateTagLength(tagNo) + 1; 077 } 078 } 079 080 void encode( 081 ASN1OutputStream out) 082 throws IOException 083 { 084 if (!empty) 085 { 086 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 087 088 if (explicit) 089 { 090 out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo); 091 out.writeLength(primitive.encodedLength()); 092 out.writeObject(primitive); 093 } 094 else 095 { 096 // 097 // need to mark constructed types... 098 // 099 int flags; 100 if (primitive.isConstructed()) 101 { 102 flags = BERTags.CONSTRUCTED | BERTags.TAGGED; 103 } 104 else 105 { 106 flags = BERTags.TAGGED; 107 } 108 109 out.writeTag(flags, tagNo); 110 out.writeImplicitObject(primitive); 111 } 112 } 113 else 114 { 115 out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES); 116 } 117 } 118}