1e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompackage org.bouncycastle.asn1.cms; 2e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 3e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Enumeration; 4e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Hashtable; 5e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Vector; 6e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 7e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable; 8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1EncodableVector; 9e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 10e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Set; 11e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.DERSet; 12e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 135db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root/** 145db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root * This is helper tool to construct {@link Attributes} sets. 155db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root */ 16e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompublic class AttributeTable 17e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom{ 18e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private Hashtable attributes = new Hashtable(); 19e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 20e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable( 21e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Hashtable attrs) 22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 23e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom attributes = copyTable(attrs); 24e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 25e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 26e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable( 27e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector v) 28e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 29e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (int i = 0; i != v.size(); i++) 30e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 31e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute a = Attribute.getInstance(v.get(i)); 32e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom addAttribute(a.getAttrType(), a); 34e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 35e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 36e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 37e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable( 38e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Set s) 39e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 40e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (int i = 0; i != s.size(); i++) 41e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 42e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute a = Attribute.getInstance(s.getObjectAt(i)); 43e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 44e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom addAttribute(a.getAttrType(), a); 45e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 46e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 47e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 48e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable( 4970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom Attribute attr) 5070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 5170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom addAttribute(attr.getAttrType(), attr); 5270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 5370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 5470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom public AttributeTable( 55e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attributes attrs) 56e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 57e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this(ASN1Set.getInstance(attrs.toASN1Primitive())); 58e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 59e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 60e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private void addAttribute( 61e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1ObjectIdentifier oid, 62e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute a) 63e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 64e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object value = attributes.get(oid); 65e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 66e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (value == null) 67e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 68e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom attributes.put(oid, a); 69e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 70e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 71e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 72e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Vector v; 73e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 74e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (value instanceof Attribute) 75e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 76e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v = new Vector(); 77e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 78e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.addElement(value); 79e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.addElement(a); 80e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 81e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 82e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 83e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v = (Vector)value; 84e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 85e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.addElement(a); 86e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 87e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 88e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom attributes.put(oid, v); 89e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 90e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 91e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 92e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 93e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return the first attribute matching the OBJECT IDENTIFIER oid. 94e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 95e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param oid type of attribute required. 96e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return first attribute found of type oid. 97e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 98e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public Attribute get( 99e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1ObjectIdentifier oid) 100e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 101e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object value = attributes.get(oid); 102e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 103e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (value instanceof Vector) 104e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 105e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return (Attribute)((Vector)value).elementAt(0); 106e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 107e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 108e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return (Attribute)value; 109e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 110e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 111e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 112e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be 113e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * empty if there are no attributes of the required type present. 114e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 115e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param oid type of attribute required. 116e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return a vector of all the attributes found of type oid. 117e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 118e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public ASN1EncodableVector getAll( 119e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1ObjectIdentifier oid) 120e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 121e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector v = new ASN1EncodableVector(); 122e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 123e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object value = attributes.get(oid); 124e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 125e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (value instanceof Vector) 126e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 127e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Enumeration e = ((Vector)value).elements(); 128e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 129e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom while (e.hasMoreElements()) 130e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 131e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.add((Attribute)e.nextElement()); 132e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 133e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 134e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else if (value != null) 135e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 136e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.add((Attribute)value); 137e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 138e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 139e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return v; 140e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 141e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 142e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public int size() 143e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 144e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom int size = 0; 145e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 146e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (Enumeration en = attributes.elements(); en.hasMoreElements();) 147e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 148e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object o = en.nextElement(); 149e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 150e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (o instanceof Vector) 151e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 152e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom size += ((Vector)o).size(); 153e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 154e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 155e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 156e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom size++; 157e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 158e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 159e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 160e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return size; 161e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 162e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 163e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public Hashtable toHashtable() 164e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 165e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return copyTable(attributes); 166e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 167e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 168e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public ASN1EncodableVector toASN1EncodableVector() 169e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 170e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector v = new ASN1EncodableVector(); 171e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Enumeration e = attributes.elements(); 172e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 173e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom while (e.hasMoreElements()) 174e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 175e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object value = e.nextElement(); 176e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 177e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (value instanceof Vector) 178e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 179e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Enumeration en = ((Vector)value).elements(); 180e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 181e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom while (en.hasMoreElements()) 182e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 183e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.add(Attribute.getInstance(en.nextElement())); 184e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 185e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 186e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 187e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 188e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.add(Attribute.getInstance(value)); 189e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 190e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 191e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 192e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return v; 193e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 194e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 195e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public Attributes toASN1Structure() 196e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 197e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return new Attributes(this.toASN1EncodableVector()); 198e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 199e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 200e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private Hashtable copyTable( 201e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Hashtable in) 202e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 203e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Hashtable out = new Hashtable(); 204e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Enumeration e = in.keys(); 205e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 206e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom while (e.hasMoreElements()) 207e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 208e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Object key = e.nextElement(); 209e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 210e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom out.put(key, in.get(key)); 211e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 212e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 213e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return out; 214e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 215e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 216e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 217e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return a new table with the passed in attribute added. 218e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 219e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param attrType 220e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param attrValue 221e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return 222e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 223e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable add(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue) 224e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 225e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable newTable = new AttributeTable(attributes); 226e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 227e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom newTable.addAttribute(attrType, new Attribute(attrType, new DERSet(attrValue))); 228e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 229e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return newTable; 230e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 231e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 232e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable remove(ASN1ObjectIdentifier attrType) 233e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 234e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable newTable = new AttributeTable(attributes); 235e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 236e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom newTable.attributes.remove(attrType); 237e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 238e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return newTable; 239e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 240e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom} 241