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