001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.util.asn1; 019 020 import java.io.ByteArrayOutputStream; 021 import java.io.IOException; 022 import java.util.Enumeration; 023 import java.util.Vector; 024 025 abstract public class ASN1Set 026 extends DERObject 027 { 028 protected Vector set = new Vector(); 029 030 /** 031 * return an ASN1Set from the given object. 032 * 033 * @param obj the object we want converted. 034 * @exception IllegalArgumentException if the object cannot be converted. 035 */ 036 public static ASN1Set getInstance( 037 Object obj) 038 { 039 if (obj == null || obj instanceof ASN1Set) 040 { 041 return (ASN1Set)obj; 042 } 043 044 throw new IllegalArgumentException("unknown object in getInstance"); 045 } 046 047 /** 048 * Return an ASN1 set from a tagged object. There is a special 049 * case here, if an object appears to have been explicitly tagged on 050 * reading but we were expecting it to be implictly tagged in the 051 * normal course of events it indicates that we lost the surrounding 052 * set - so we need to add it back (this will happen if the tagged 053 * object is a sequence that contains other sequences). If you are 054 * dealing with implicitly tagged sets you really <b>should</b> 055 * be using this method. 056 * 057 * @param obj the tagged object. 058 * @param explicit true if the object is meant to be explicitly tagged 059 * false otherwise. 060 * @exception IllegalArgumentException if the tagged object cannot 061 * be converted. 062 */ 063 public static ASN1Set getInstance( 064 ASN1TaggedObject obj, 065 boolean explicit) 066 { 067 if (explicit) 068 { 069 if (!obj.isExplicit()) 070 { 071 throw new IllegalArgumentException("object implicit - explicit expected."); 072 } 073 074 return (ASN1Set)obj.getObject(); 075 } 076 else 077 { 078 // 079 // constructed object which appears to be explicitly tagged 080 // and it's really implicit means we have to add the 081 // surrounding sequence. 082 // 083 if (obj.isExplicit()) 084 { 085 ASN1Set set = new DERSet(obj.getObject()); 086 087 return set; 088 } 089 else 090 { 091 if (obj.getObject() instanceof ASN1Set) 092 { 093 return (ASN1Set)obj.getObject(); 094 } 095 096 // 097 // in this case the parser returns a sequence, convert it 098 // into a set. 099 // 100 ASN1EncodableVector v = new ASN1EncodableVector(); 101 102 if (obj.getObject() instanceof ASN1Sequence) 103 { 104 ASN1Sequence s = (ASN1Sequence)obj.getObject(); 105 Enumeration e = s.getObjects(); 106 107 while (e.hasMoreElements()) 108 { 109 v.add((DEREncodable)e.nextElement()); 110 } 111 112 return new DERSet(v, false); 113 } 114 } 115 } 116 117 throw new IllegalArgumentException( 118 "unknown object in getInstanceFromTagged"); 119 } 120 121 public ASN1Set() 122 { 123 } 124 125 public Enumeration getObjects() 126 { 127 return set.elements(); 128 } 129 130 /** 131 * return the object at the set postion indicated by index. 132 * 133 * @param index the set number (starting at zero) of the object 134 * @return the object at the set postion indicated by index. 135 */ 136 public DEREncodable getObjectAt( 137 int index) 138 { 139 return (DEREncodable)set.elementAt(index); 140 } 141 142 /** 143 * return the number of objects in this set. 144 * 145 * @return the number of objects in this set. 146 */ 147 public int size() 148 { 149 return set.size(); 150 } 151 152 public int hashCode() 153 { 154 Enumeration e = this.getObjects(); 155 int hashCode = 0; 156 157 while (e.hasMoreElements()) 158 { 159 hashCode ^= e.nextElement().hashCode(); 160 } 161 162 return hashCode; 163 } 164 165 public boolean equals( 166 Object o) 167 { 168 if (o == null || !(o instanceof ASN1Set)) 169 { 170 return false; 171 } 172 173 ASN1Set other = (ASN1Set)o; 174 175 if (this.size() != other.size()) 176 { 177 return false; 178 } 179 180 Enumeration s1 = this.getObjects(); 181 Enumeration s2 = other.getObjects(); 182 183 while (s1.hasMoreElements()) 184 { 185 if (!s1.nextElement().equals(s2.nextElement())) 186 { 187 return false; 188 } 189 } 190 191 return true; 192 } 193 194 /** 195 * return true if a <= b (arrays are assumed padded with zeros). 196 */ 197 private boolean lessThanOrEqual( 198 byte[] a, 199 byte[] b) 200 { 201 if (a.length <= b.length) 202 { 203 for (int i = 0; i != a.length; i++) 204 { 205 int l = a[i] & 0xff; 206 int r = b[i] & 0xff; 207 208 if (r > l) 209 { 210 return true; 211 } 212 else if (l > r) 213 { 214 return false; 215 } 216 } 217 218 return true; 219 } 220 else 221 { 222 for (int i = 0; i != b.length; i++) 223 { 224 int l = a[i] & 0xff; 225 int r = b[i] & 0xff; 226 227 if (r > l) 228 { 229 return true; 230 } 231 else if (l > r) 232 { 233 return false; 234 } 235 } 236 237 return false; 238 } 239 } 240 241 private byte[] getEncoded( 242 DEREncodable obj) 243 { 244 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 245 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 246 247 try 248 { 249 aOut.writeObject(obj); 250 } 251 catch (IOException e) 252 { 253 throw new IllegalArgumentException("cannot encode object added to SET", e); 254 } 255 256 return bOut.toByteArray(); 257 } 258 259 protected void sort() 260 { 261 if (set.size() > 1) 262 { 263 boolean swapped = true; 264 265 while (swapped) 266 { 267 int index = 0; 268 byte[] a = getEncoded((DEREncodable)set.elementAt(0)); 269 270 swapped = false; 271 272 while (index != set.size() - 1) 273 { 274 byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1)); 275 276 if (lessThanOrEqual(a, b)) 277 { 278 a = b; 279 } 280 else 281 { 282 Object o = set.elementAt(index); 283 284 set.setElementAt(set.elementAt(index + 1), index); 285 set.setElementAt(o, index + 1); 286 287 swapped = true; 288 } 289 290 index++; 291 } 292 } 293 } 294 } 295 296 protected void addObject( 297 DEREncodable obj) 298 { 299 set.addElement(obj); 300 } 301 302 abstract void encode(DEROutputStream out) 303 throws IOException; 304 }