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 }