001 package org.apache.commons.ssl.asn1; 002 003 import java.io.ByteArrayOutputStream; 004 import java.io.IOException; 005 006 /** Base class for an application specific object */ 007 public class DERApplicationSpecific 008 extends ASN1Object { 009 private int tag; 010 private byte[] octets; 011 012 public DERApplicationSpecific( 013 int tag, 014 byte[] octets) { 015 this.tag = tag; 016 this.octets = octets; 017 } 018 019 public DERApplicationSpecific( 020 int tag, 021 DEREncodable object) 022 throws IOException { 023 this(true, tag, object); 024 } 025 026 public DERApplicationSpecific( 027 boolean explicit, 028 int tag, 029 DEREncodable object) 030 throws IOException { 031 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 032 DEROutputStream dos = new DEROutputStream(bOut); 033 034 dos.writeObject(object); 035 036 byte[] data = bOut.toByteArray(); 037 038 if (tag >= 0x1f) { 039 throw new IOException("unsupported tag number"); 040 } 041 042 if (explicit) { 043 this.tag = tag | DERTags.CONSTRUCTED; 044 this.octets = data; 045 } else { 046 this.tag = tag; 047 int lenBytes = getLengthOfLength(data); 048 byte[] tmp = new byte[data.length - lenBytes]; 049 System.arraycopy(data, lenBytes, tmp, 0, tmp.length); 050 this.octets = tmp; 051 } 052 } 053 054 private int getLengthOfLength(byte[] data) { 055 int count = 2; // TODO: assumes only a 1 byte tag number 056 057 while ((data[count - 1] & 0x80) != 0) { 058 count++; 059 } 060 061 return count; 062 } 063 064 public boolean isConstructed() { 065 return (tag & DERTags.CONSTRUCTED) != 0; 066 } 067 068 public byte[] getContents() { 069 return octets; 070 } 071 072 public int getApplicationTag() { 073 return tag; 074 } 075 076 public DERObject getObject() 077 throws IOException { 078 return new ASN1InputStream(getContents()).readObject(); 079 } 080 081 /** 082 * Return the enclosed object assuming implicit tagging. 083 * 084 * @param derTagNo the type tag that should be applied to the object's contents. 085 * @return the resulting object 086 * @throws IOException if reconstruction fails. 087 */ 088 public DERObject getObject(int derTagNo) 089 throws IOException { 090 if (tag >= 0x1f) { 091 throw new IOException("unsupported tag number"); 092 } 093 094 byte[] tmp = this.getEncoded(); 095 096 tmp[0] = (byte) derTagNo; 097 098 return new ASN1InputStream(tmp).readObject(); 099 } 100 101 /* (non-Javadoc) 102 * @see org.apache.commons.ssl.asn1.DERObject#encode(org.apache.commons.ssl.asn1.DEROutputStream) 103 */ 104 void encode(DEROutputStream out) throws IOException { 105 out.writeEncoded(DERTags.APPLICATION | tag, octets); 106 } 107 108 boolean asn1Equals( 109 DERObject o) { 110 if (!(o instanceof DERApplicationSpecific)) { 111 return false; 112 } 113 114 DERApplicationSpecific other = (DERApplicationSpecific) o; 115 116 if (tag != other.tag) { 117 return false; 118 } 119 120 if (octets.length != other.octets.length) { 121 return false; 122 } 123 124 for (int i = 0; i < octets.length; i++) { 125 if (octets[i] != other.octets[i]) { 126 return false; 127 } 128 } 129 130 return true; 131 } 132 133 public int hashCode() { 134 byte[] b = this.getContents(); 135 int value = 0; 136 137 for (int i = 0; i != b.length; i++) { 138 value ^= (b[i] & 0xff) << (i % 4); 139 } 140 141 return value ^ this.getApplicationTag(); 142 } 143 }