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.ASN1ObjectIdentifier;
      8 import org.bouncycastle.asn1.ASN1Sequence;
      9 import org.bouncycastle.asn1.ASN1TaggedObject;
     10 import org.bouncycastle.asn1.DEREncodable;
     11 import org.bouncycastle.asn1.DERObject;
     12 import org.bouncycastle.asn1.DERSequence;
     13 import org.bouncycastle.asn1.x500.style.BCStyle;
     14 import org.bouncycastle.asn1.x509.X509Name;
     15 
     16 /**
     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 ASN1Encodable
     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     public X500Name(X500NameStyle style, X500Name name)
     43     {
     44         this.rdns = name.rdns;
     45         this.style = style;
     46     }
     47 
     48     /**
     49      * Return a X509Name based on the passed in tagged object.
     50      *
     51      * @param obj tag object holding name.
     52      * @param explicit true if explicitly tagged false otherwise.
     53      * @return the X509Name
     54      */
     55     public static X500Name getInstance(
     56         ASN1TaggedObject obj,
     57         boolean          explicit)
     58     {
     59         // must be true as choice item
     60         return getInstance(ASN1Sequence.getInstance(obj, true));
     61     }
     62 
     63     public static X500Name getInstance(
     64         Object  obj)
     65     {
     66         if (obj instanceof X500Name)
     67         {
     68             return (X500Name)obj;
     69         }
     70         else if (obj instanceof X509Name)
     71         {
     72             return new X500Name(ASN1Sequence.getInstance(((X509Name)obj).getDERObject()));
     73         }
     74         else if (obj != null)
     75         {
     76             return new X500Name(ASN1Sequence.getInstance(obj));
     77         }
     78 
     79         return null;
     80     }
     81 
     82     /**
     83      * Constructor from ASN1Sequence
     84      *
     85      * the principal will be a list of constructed sets, each containing an (OID, String) pair.
     86      */
     87     private X500Name(
     88         ASN1Sequence  seq)
     89     {
     90         this(defaultStyle, seq);
     91     }
     92 
     93     private X500Name(
     94         X500NameStyle style,
     95         ASN1Sequence  seq)
     96     {
     97         this.style = style;
     98         this.rdns = new RDN[seq.size()];
     99 
    100         int index = 0;
    101 
    102         for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
    103         {
    104             rdns[index++] = RDN.getInstance(e.nextElement());
    105         }
    106     }
    107 
    108     public X500Name(
    109         RDN[] rDNs)
    110     {
    111         this(defaultStyle, rDNs);
    112     }
    113 
    114     public X500Name(
    115         X500NameStyle style,
    116         RDN[]         rDNs)
    117     {
    118         this.rdns = rDNs;
    119         this.style = style;
    120     }
    121 
    122     public X500Name(
    123         String dirName)
    124     {
    125         this(defaultStyle, dirName);
    126     }
    127 
    128     public X500Name(
    129         X500NameStyle style,
    130         String        dirName)
    131     {
    132         this(style.fromString(dirName));
    133 
    134         this.style = style;
    135     }
    136 
    137     /**
    138      * return an array of RDNs in structure order.
    139      *
    140      * @return an array of RDN objects.
    141      */
    142     public RDN[] getRDNs()
    143     {
    144         RDN[] tmp = new RDN[this.rdns.length];
    145 
    146         System.arraycopy(rdns, 0, tmp, 0, tmp.length);
    147 
    148         return tmp;
    149     }
    150 
    151     /**
    152      * return an array of RDNs containing the attribute type given by OID in structure order.
    153      *
    154      * @param oid the type OID we are looking for.
    155      * @return an array, possibly zero length, of RDN objects.
    156      */
    157     public RDN[] getRDNs(ASN1ObjectIdentifier oid)
    158     {
    159         RDN[] res = new RDN[rdns.length];
    160         int   count = 0;
    161 
    162         for (int i = 0; i != rdns.length; i++)
    163         {
    164             RDN rdn = rdns[i];
    165 
    166             if (rdn.isMultiValued())
    167             {
    168                 AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
    169                 for (int j = 0; j != attr.length; j++)
    170                 {
    171                     if (attr[j].getType().equals(oid))
    172                     {
    173                         res[count++] = rdn;
    174                         break;
    175                     }
    176                 }
    177             }
    178             else
    179             {
    180                 if (rdn.getFirst().getType().equals(oid))
    181                 {
    182                     res[count++] = rdn;
    183                 }
    184             }
    185         }
    186 
    187         RDN[] tmp = new RDN[count];
    188 
    189         System.arraycopy(res, 0, tmp, 0, tmp.length);
    190 
    191         return tmp;
    192     }
    193 
    194     public DERObject toASN1Object()
    195     {
    196         return new DERSequence(rdns);
    197     }
    198 
    199     public int hashCode()
    200     {
    201         if (isHashCodeCalculated)
    202         {
    203             return hashCodeValue;
    204         }
    205 
    206         isHashCodeCalculated = true;
    207 
    208         hashCodeValue = style.calculateHashCode(this);
    209 
    210         return hashCodeValue;
    211     }
    212 
    213     /**
    214      * test for equality - note: case is ignored.
    215      */
    216     public boolean equals(Object obj)
    217     {
    218         if (obj == this)
    219         {
    220             return true;
    221         }
    222 
    223         if (!(obj instanceof X500Name || obj instanceof ASN1Sequence))
    224         {
    225             return false;
    226         }
    227 
    228         DERObject derO = ((DEREncodable)obj).getDERObject();
    229 
    230         if (this.getDERObject().equals(derO))
    231         {
    232             return true;
    233         }
    234 
    235         try
    236         {
    237             return style.areEqual(this, new X500Name(ASN1Sequence.getInstance(((DEREncodable)obj).getDERObject())));
    238         }
    239         catch (Exception e)
    240         {
    241             return false;
    242         }
    243     }
    244 
    245     public String toString()
    246     {
    247         return style.toString(this);
    248     }
    249 
    250     /**
    251      * Set the default style for X500Name construction.
    252      *
    253      * @param style  an X500NameStyle
    254      */
    255     public static void setDefaultStyle(X500NameStyle style)
    256     {
    257         if (style == null)
    258         {
    259             throw new NullPointerException("cannot set style to null");
    260         }
    261 
    262         defaultStyle = style;
    263     }
    264 
    265     /**
    266      * Return the current default style.
    267      *
    268      * @return default style for X500Name construction.
    269      */
    270     public static X500NameStyle getDefaultStyle()
    271     {
    272         return defaultStyle;
    273     }
    274 }
    275