001 package org.apache.commons.ssl.asn1; 002 003 import java.io.IOException; 004 import java.util.Enumeration; 005 import java.util.Vector; 006 007 public abstract class ASN1Sequence 008 extends ASN1Object { 009 private Vector seq = new Vector(); 010 011 /** 012 * return an ASN1Sequence from the given object. 013 * 014 * @param obj the object we want converted. 015 * @throws IllegalArgumentException if the object cannot be converted. 016 */ 017 public static ASN1Sequence getInstance( 018 Object obj) { 019 if (obj == null || obj instanceof ASN1Sequence) { 020 return (ASN1Sequence) obj; 021 } 022 023 throw new IllegalArgumentException("unknown object in getInstance"); 024 } 025 026 /** 027 * Return an ASN1 sequence from a tagged object. There is a special 028 * case here, if an object appears to have been explicitly tagged on 029 * reading but we were expecting it to be implictly tagged in the 030 * normal course of events it indicates that we lost the surrounding 031 * sequence - so we need to add it back (this will happen if the tagged 032 * object is a sequence that contains other sequences). If you are 033 * dealing with implicitly tagged sequences you really <b>should</b> 034 * be using this method. 035 * 036 * @param obj the tagged object. 037 * @param explicit true if the object is meant to be explicitly tagged, 038 * false otherwise. 039 * @throws IllegalArgumentException if the tagged object cannot 040 * be converted. 041 */ 042 public static ASN1Sequence getInstance( 043 ASN1TaggedObject obj, 044 boolean explicit) { 045 if (explicit) { 046 if (!obj.isExplicit()) { 047 throw new IllegalArgumentException("object implicit - explicit expected."); 048 } 049 050 return (ASN1Sequence) obj.getObject(); 051 } else { 052 // 053 // constructed object which appears to be explicitly tagged 054 // when it should be implicit means we have to add the 055 // surrounding sequence. 056 // 057 if (obj.isExplicit()) { 058 if (obj instanceof BERTaggedObject) { 059 return new BERSequence(obj.getObject()); 060 } else { 061 return new DERSequence(obj.getObject()); 062 } 063 } else { 064 if (obj.getObject() instanceof ASN1Sequence) { 065 return (ASN1Sequence) obj.getObject(); 066 } 067 } 068 } 069 070 throw new IllegalArgumentException( 071 "unknown object in getInstanceFromTagged"); 072 } 073 074 public Enumeration getObjects() { 075 return seq.elements(); 076 } 077 078 public ASN1SequenceParser parser() { 079 final ASN1Sequence outer = this; 080 081 return new ASN1SequenceParser() { 082 private final int max = size(); 083 084 private int index; 085 086 public DEREncodable readObject() throws IOException { 087 if (index == max) { 088 return null; 089 } 090 091 DEREncodable obj = getObjectAt(index++); 092 if (obj instanceof ASN1Sequence) { 093 return ((ASN1Sequence) obj).parser(); 094 } 095 if (obj instanceof ASN1Set) { 096 return ((ASN1Set) obj).parser(); 097 } 098 099 return obj; 100 } 101 102 public DERObject getDERObject() { 103 return outer; 104 } 105 }; 106 } 107 108 /** 109 * return the object at the sequence postion indicated by index. 110 * 111 * @param index the sequence number (starting at zero) of the object 112 * @return the object at the sequence postion indicated by index. 113 */ 114 public DEREncodable getObjectAt( 115 int index) { 116 return (DEREncodable) seq.elementAt(index); 117 } 118 119 /** 120 * return the number of objects in this sequence. 121 * 122 * @return the number of objects in this sequence. 123 */ 124 public int size() { 125 return seq.size(); 126 } 127 128 public int hashCode() { 129 Enumeration e = this.getObjects(); 130 int hashCode = 0; 131 132 while (e.hasMoreElements()) { 133 Object o = e.nextElement(); 134 135 if (o != null) { 136 hashCode ^= o.hashCode(); 137 } 138 } 139 140 return hashCode; 141 } 142 143 boolean asn1Equals( 144 DERObject o) { 145 if (!(o instanceof ASN1Sequence)) { 146 return false; 147 } 148 149 ASN1Sequence other = (ASN1Sequence) o; 150 151 if (this.size() != other.size()) { 152 return false; 153 } 154 155 Enumeration s1 = this.getObjects(); 156 Enumeration s2 = other.getObjects(); 157 158 while (s1.hasMoreElements()) { 159 DERObject o1 = ((DEREncodable) s1.nextElement()).getDERObject(); 160 DERObject o2 = ((DEREncodable) s2.nextElement()).getDERObject(); 161 162 if (o1 == o2 || (o1 != null && o1.equals(o2))) { 163 continue; 164 } 165 166 return false; 167 } 168 169 return true; 170 } 171 172 protected void addObject( 173 DEREncodable obj) { 174 seq.addElement(obj); 175 } 176 177 abstract void encode(DEROutputStream out) 178 throws IOException; 179 180 public String toString() { 181 return seq.toString(); 182 } 183 }