Home | History | Annotate | Download | only in x500
      1 package org.bouncycastle.asn1.x500;
      2 
      3 import java.util.Enumeration;
      4 
      5 import org.bouncycastle.asn1.ASN1Choice;
      6 import org.bouncycastle.asn1.ASN1Encodable;
      7 import org.bouncycastle.asn1.ASN1Object;
      8 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
      9 import org.bouncycastle.asn1.ASN1Primitive;
     10 import org.bouncycastle.asn1.ASN1Sequence;
     11 import org.bouncycastle.asn1.ASN1TaggedObject;
     12 import org.bouncycastle.asn1.DERSequence;
     13 import org.bouncycastle.asn1.x500.style.BCStyle;
     14 
     15 /**
     16  * The X.500 Name object.
     17  * <pre>
     18  *     Name ::= CHOICE {
     19  *                       RDNSequence }
     20  *
     21  *     RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     22  *
     23  *     RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
     24  *
     25  *     AttributeTypeAndValue ::= SEQUENCE {
     26  *                                   type  OBJECT IDENTIFIER,
     27  *                                   value ANY }
     28  * </pre>
     29  */
     30 public class X500Name
     31     extends ASN1Object
     32     implements ASN1Choice
     33 {
     34     private static X500NameStyle    defaultStyle = BCStyle.INSTANCE;
     35 
     36     private boolean                 isHashCodeCalculated;
     37     private int                     hashCodeValue;
     38 
     39     private X500NameStyle style;
     40     private RDN[] rdns;
     41 
     42     /**
     43      * @deprecated use the getInstance() method that takes a style.
     44      */
     45     public X500Name(X500NameStyle style, X500Name name)
     46     {
     47         this.rdns = name.rdns;
     48         this.style = style;
     49     }
     50 
     51     /**
     52      * Return a X500Name based on the passed in tagged object.
     53      *
     54      * @param obj tag object holding name.
     55      * @param explicit true if explicitly tagged false otherwise.
     56      * @return the X500Name
     57      */
     58     public static X500Name getInstance(
     59         ASN1TaggedObject obj,
     60         boolean          explicit)
     61     {
     62         // must be true as choice item
     63         return getInstance(ASN1Sequence.getInstance(obj, true));
     64     }
     65 
     66     public static X500Name getInstance(
     67         Object  obj)
     68     {
     69         if (obj instanceof X500Name)
     70         {
     71             return (X500Name)obj;
     72         }
     73         else if (obj != null)
     74         {
     75             return new X500Name(ASN1Sequence.getInstance(obj));
     76         }
     77 
     78         return null;
     79     }
     80 
     81     public static X500Name getInstance(
     82         X500NameStyle style,
     83         Object        obj)
     84     {
     85         if (obj instanceof X500Name)
     86         {
     87             return new X500Name(style, (X500Name)obj);
     88         }
     89         else if (obj != null)
     90         {
     91             return new X500Name(style, ASN1Sequence.getInstance(obj));
     92         }
     93 
     94         return null;
     95     }
     96 
     97     /**
     98      * Constructor from ASN1Sequence
     99      *
    100      * the principal will be a list of constructed sets, each containing an (OID, String) pair.
    101      */
    102     private X500Name(
    103         ASN1Sequence  seq)
    104     {
    105         this(defaultStyle, seq);
    106     }
    107 
    108     private X500Name(
    109         X500NameStyle style,
    110         ASN1Sequence  seq)
    111     {
    112         this.style = style;
    113         this.rdns = new RDN[seq.size()];
    114 
    115         int index = 0;
    116 
    117         for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
    118         {
    119             rdns[index++] = RDN.getInstance(e.nextElement());
    120         }
    121     }
    122 
    123     public X500Name(
    124         RDN[] rDNs)
    125     {
    126         this(defaultStyle, rDNs);
    127     }
    128 
    129     public X500Name(
    130         X500NameStyle style,
    131         RDN[]         rDNs)
    132     {
    133         this.rdns = rDNs;
    134         this.style = style;
    135     }
    136 
    137     public X500Name(
    138         String dirName)
    139     {
    140         this(defaultStyle, dirName);
    141     }
    142 
    143     public X500Name(
    144         X500NameStyle style,
    145         String        dirName)
    146     {
    147         this(style.fromString(dirName));
    148 
    149         this.style = style;
    150     }
    151 
    152     /**
    153      * return an array of RDNs in structure order.
    154      *
    155      * @return an array of RDN objects.
    156      */
    157     public RDN[] getRDNs()
    158     {
    159         RDN[] tmp = new RDN[this.rdns.length];
    160 
    161         System.arraycopy(rdns, 0, tmp, 0, tmp.length);
    162 
    163         return tmp;
    164     }
    165 
    166     /**
    167      * return an array of OIDs contained in the attribute type of each RDN in structure order.
    168      *
    169      * @return an array, possibly zero length, of ASN1ObjectIdentifiers objects.
    170      */
    171     public ASN1ObjectIdentifier[] getAttributeTypes()
    172     {
    173         int   count = 0;
    174 
    175         for (int i = 0; i != rdns.length; i++)
    176         {
    177             RDN rdn = rdns[i];
    178 
    179             count += rdn.size();
    180         }
    181 
    182         ASN1ObjectIdentifier[] res = new ASN1ObjectIdentifier[count];
    183 
    184         count = 0;
    185 
    186         for (int i = 0; i != rdns.length; i++)
    187         {
    188             RDN rdn = rdns[i];
    189 
    190             if (rdn.isMultiValued())
    191             {
    192                 AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
    193                 for (int j = 0; j != attr.length; j++)
    194                 {
    195                     res[count++] = attr[j].getType();
    196                 }
    197             }
    198             else if (rdn.size() != 0)
    199             {
    200                 res[count++] = rdn.getFirst().getType();
    201             }
    202         }
    203 
    204         return res;
    205     }
    206 
    207     /**
    208      * return an array of RDNs containing the attribute type given by OID in structure order.
    209      *
    210      * @param attributeType the type OID we are looking for.
    211      * @return an array, possibly zero length, of RDN objects.
    212      */
    213     public RDN[] getRDNs(ASN1ObjectIdentifier attributeType)
    214     {
    215         RDN[] res = new RDN[rdns.length];
    216         int   count = 0;
    217 
    218         for (int i = 0; i != rdns.length; i++)
    219         {
    220             RDN rdn = rdns[i];
    221 
    222             if (rdn.isMultiValued())
    223             {
    224                 AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
    225                 for (int j = 0; j != attr.length; j++)
    226                 {
    227                     if (attr[j].getType().equals(attributeType))
    228                     {
    229                         res[count++] = rdn;
    230                         break;
    231                     }
    232                 }
    233             }
    234             else
    235             {
    236                 if (rdn.getFirst().getType().equals(attributeType))
    237                 {
    238                     res[count++] = rdn;
    239                 }
    240             }
    241         }
    242 
    243         RDN[] tmp = new RDN[count];
    244 
    245         System.arraycopy(res, 0, tmp, 0, tmp.length);
    246 
    247         return tmp;
    248     }
    249 
    250     public ASN1Primitive toASN1Primitive()
    251     {
    252         return new DERSequence(rdns);
    253     }
    254 
    255     public int hashCode()
    256     {
    257         if (isHashCodeCalculated)
    258         {
    259             return hashCodeValue;
    260         }
    261 
    262         isHashCodeCalculated = true;
    263 
    264         hashCodeValue = style.calculateHashCode(this);
    265 
    266         return hashCodeValue;
    267     }
    268 
    269     /**
    270      * test for equality - note: case is ignored.
    271      */
    272     public boolean equals(Object obj)
    273     {
    274         if (obj == this)
    275         {
    276             return true;
    277         }
    278 
    279         if (!(obj instanceof X500Name || obj instanceof ASN1Sequence))
    280         {
    281             return false;
    282         }
    283 
    284         ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
    285 
    286         if (this.toASN1Primitive().equals(derO))
    287         {
    288             return true;
    289         }
    290 
    291         try
    292         {
    293             return style.areEqual(this, new X500Name(ASN1Sequence.getInstance(((ASN1Encodable)obj).toASN1Primitive())));
    294         }
    295         catch (Exception e)
    296         {
    297             return false;
    298         }
    299     }
    300 
    301     public String toString()
    302     {
    303         return style.toString(this);
    304     }
    305 
    306     /**
    307      * Set the default style for X500Name construction.
    308      *
    309      * @param style  an X500NameStyle
    310      */
    311     public static void setDefaultStyle(X500NameStyle style)
    312     {
    313         if (style == null)
    314         {
    315             throw new NullPointerException("cannot set style to null");
    316         }
    317 
    318         defaultStyle = style;
    319     }
    320 
    321     /**
    322      * Return the current default style.
    323      *
    324      * @return default style for X500Name construction.
    325      */
    326     public static X500NameStyle getDefaultStyle()
    327     {
    328         return defaultStyle;
    329     }
    330 }
    331