KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > security > auth > x500 > X500Principal


1 /*
2  * @(#)X500Principal.java 1.21 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.security.auth.x500;
9
10 import java.io.*;
11 import java.security.Principal JavaDoc;
12 import sun.security.x509.X500Name;
13 import sun.security.util.*;
14
15 /**
16  * <p> This class represents an X.500 <code>Principal</code>.
17  * <code>X500Principal</code>s are represented by distinguished names such as
18  * "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US".
19  *
20  * <p> This class can be instantiated by using a string representation
21  * of the distinguished name, or by using the ASN.1 DER encoded byte
22  * representation of the distinguished name. The current specification
23  * for the string representation of a distinguished name is defined in
24  * <a HREF="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>.
25  * This class, however, accepts string formats from both RFC 2253 and
26  * <a HREF="http://www.ietf.org/rfc/rfc1779.txt">RFC 1779</a>,
27  * and also recognizes attribute type keywords whose OIDs
28  * (Object Identifiers) are defined in
29  * <a HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC 2459</a>.
30  *
31  * <p> The string representation for this <code>X500Principal</code>
32  * can be obtained by calling the <code>getName</code> methods.
33  *
34  * <p> Note that the <code>getSubjectX500Principal</code> and
35  * <code>getIssuerX500Principal</code> methods of
36  * <code>X509Certificate</code> return X500Principals representing the
37  * issuer and subject fields of the certificate.
38  *
39  * @version 1.21, 12/19/03
40  * @see java.security.cert.X509Certificate
41  * @since 1.4
42  */

43 public final class X500Principal implements Principal JavaDoc, java.io.Serializable JavaDoc {
44
45     private static final long serialVersionUID = -500463348111345721L;
46
47     /**
48      * RFC 1779 String format of Distinguished Names.
49      */

50     public static final String JavaDoc RFC1779 = "RFC1779";
51     /**
52      * RFC 2253 String format of Distinguished Names.
53      */

54     public static final String JavaDoc RFC2253 = "RFC2253";
55     /**
56      * Canonical String format of Distinguished Names.
57      */

58     public static final String JavaDoc CANONICAL = "CANONICAL";
59
60     /**
61      * The X500Name representing this principal.
62      *
63      * NOTE: this field is reflectively accessed from within X500Name.
64      */

65     private transient X500Name thisX500Name;
66     
67     /**
68      * Creates an X500Principal by wrapping an X500Name.
69      *
70      * NOTE: The constructor is package private. It is intended to be accessed
71      * using privileged reflection from classes in sun.security.*.
72      * Currently referenced from sun.security.x509.X500Name.asX500Principal().
73      */

74     X500Principal(X500Name x500Name) {
75         thisX500Name = x500Name;
76     }
77
78     /**
79      * Creates an <code>X500Principal</code> from a string representation of
80      * an X.500 distinguished name (ex:
81      * "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").
82      * The distinguished name must be specified using the grammar defined in
83      * RFC 1779 or RFC 2253 (either format is acceptable).
84      *
85      * <p>This constructor recognizes the attribute type keywords
86      * defined in RFC 1779 and RFC 2253
87      * (and listed in {@link #getName(String format) getName(String format)}),
88      * as well as the T, DNQ or DNQUALIFIER, SURNAME, GIVENNAME, INITIALS,
89      * GENERATION, EMAILADDRESS, and SERIALNUMBER keywords whose OIDs are
90      * defined in RFC 2459 and its successor.
91      * Any other attribute type must be specified as an OID.
92      *
93      * @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
94      * @exception NullPointerException if the <code>name</code>
95      * is <code>null</code>
96      * @exception IllegalArgumentException if the <code>name</code>
97      * is improperly specified
98      */

99     public X500Principal(String JavaDoc name) {
100     if (name == null) {
101         throw new NullPointerException JavaDoc
102         (sun.security.util.ResourcesMgr.getString
103         ("provided null name"));
104     }
105
106     try {
107         thisX500Name = new X500Name(name);
108     } catch (Exception JavaDoc e) {
109         IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc
110             ("improperly specified input name: " + name);
111         iae.initCause(e);
112         throw iae;
113     }
114
115     }
116
117     /**
118      * Creates an <code>X500Principal</code> from a distinguished name in
119      * ASN.1 DER encoded form. The ASN.1 notation for this structure is as
120      * follows.
121      * <pre><code>
122      * Name ::= CHOICE {
123      * RDNSequence }
124      *
125      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
126      *
127      * RelativeDistinguishedName ::=
128      * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
129      *
130      * AttributeTypeAndValue ::= SEQUENCE {
131      * type AttributeType,
132      * value AttributeValue }
133      *
134      * AttributeType ::= OBJECT IDENTIFIER
135      *
136      * AttributeValue ::= ANY DEFINED BY AttributeType
137      * ....
138      * DirectoryString ::= CHOICE {
139      * teletexString TeletexString (SIZE (1..MAX)),
140      * printableString PrintableString (SIZE (1..MAX)),
141      * universalString UniversalString (SIZE (1..MAX)),
142      * utf8String UTF8String (SIZE (1.. MAX)),
143      * bmpString BMPString (SIZE (1..MAX)) }
144      * </code></pre>
145      *
146      * @param name a byte array containing the distinguished name in ASN.1
147      * DER encoded form
148      * @throws IllegalArgumentException if an encoding error occurs
149      * (incorrect form for DN)
150      */

151     public X500Principal(byte[] name) {
152     try {
153         thisX500Name = new X500Name(name);
154     } catch (Exception JavaDoc e) {
155         IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc
156             ("improperly specified input name");
157         iae.initCause(e);
158         throw iae;
159     }
160     }
161
162     /**
163      * Creates an <code>X500Principal</code> from an <code>InputStream</code>
164      * containing the distinguished name in ASN.1 DER encoded form.
165      * The ASN.1 notation for this structure is supplied in the
166      * documentation for
167      * {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
168      *
169      * <p> The read position of the input stream is positioned
170      * to the next available byte after the encoded distinguished name.
171      *
172      * @param is an <code>InputStream</code> containing the distinguished
173      * name in ASN.1 DER encoded form
174      *
175      * @exception NullPointerException if the <code>InputStream</code>
176      * is <code>null</code>
177      * @exception IllegalArgumentException if an encoding error occurs
178      * (incorrect form for DN)
179      */

180     public X500Principal(InputStream is) {
181     if (is == null) {
182         throw new NullPointerException JavaDoc("provided null input stream");
183     }
184
185     try {
186         if (is.markSupported())
187         is.mark(is.available() + 1);
188         DerValue der = new DerValue(is);
189         thisX500Name = new X500Name(der.data);
190     } catch (Exception JavaDoc e) {
191         if (is.markSupported()) {
192         try {
193             is.reset();
194         } catch (IOException ioe) {
195             IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc
196             ("improperly specified input stream " +
197             ("and unable to reset input stream"));
198             iae.initCause(e);
199             throw iae;
200         }
201         }
202         IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc
203             ("improperly specified input stream");
204         iae.initCause(e);
205         throw iae;
206     }
207     }
208
209     /**
210      * Returns a string representation of the X.500 distinguished name using
211      * the format defined in RFC 2253.
212      *
213      * <p>This method is equivalent to calling
214      * <code>getName(X500Principal.RFC2253)</code>.
215      *
216      * @return the distinguished name of this <code>X500Principal</code>
217      */

218     public String JavaDoc getName() {
219     return getName(X500Principal.RFC2253);
220     }
221
222     /**
223      * Returns a string representation of the X.500 distinguished name
224      * using the specified format. Valid values for the format are
225      * "RFC1779", "RFC2253", and "CANONICAL" (case insensitive).
226      *
227      * <p> If "RFC1779" is specified as the format,
228      * this method emits the attribute type keywords defined in
229      * RFC 1779 (CN, L, ST, O, OU, C, STREET).
230      * Any other attribute type is emitted as an OID.
231      *
232      * <p> If "RFC2253" is specified as the format,
233      * this method emits the attribute type keywords defined in
234      * RFC 2253 (CN, L, ST, O, OU, C, STREET, DC, UID).
235      * Any other attribute type is emitted as an OID.
236      * Under a strict reading, RFC 2253 only specifies a UTF-8 string
237      * representation. The String returned by this method is the
238      * Unicode string achieved by decoding this UTF-8 representation.
239      *
240      * <p> If "CANONICAL" is specified as the format,
241      * this method returns an RFC 2253 conformant string representation
242      * with the following additional canonicalizations:
243      *
244      * <p><ol>
245      * <li> Leading zeros are removed from attribute types
246      * that are encoded as dotted decimal OIDs
247      * <li> DirectoryString attribute values of type
248      * PrintableString and UTF8String are not
249      * output in hexadecimal format
250      * <li> DirectoryString attribute values of types
251      * other than PrintableString and UTF8String
252      * are output in hexadecimal format
253      * <li> Leading and trailing white space characters
254      * are removed from non-hexadecimal attribute values
255      * (unless the value consists entirely of white space characters)
256      * <li> Internal substrings of one or more white space characters are
257      * converted to a single space in non-hexadecimal
258      * attribute values
259      * <li> Relative Distinguished Names containing more than one
260      * Attribute Value Assertion (AVA) are output in the
261      * following order: an alphabetical ordering of AVAs
262      * containing standard keywords, followed by a numeric
263      * ordering of AVAs containing OID keywords.
264      * <li> The only characters in attribute values that are escaped are
265      * those which section 2.4 of RFC 2253 states must be escaped
266      * (they are escaped using a preceding backslash character)
267      * <li> The entire name is converted to upper case
268      * using <code>String.toUpperCase(Locale.US)</code>
269      * <li> The entire name is converted to lower case
270      * using <code>String.toLowerCase(Locale.US)</code>
271      * <li> The name is finally normalized using normalization form KD,
272      * as described in the Unicode Standard and UAX #15
273      * </ol>
274      *
275      * <p> Additional standard formats may be introduced in the future.
276      *
277      * @param format the format to use
278      *
279      * @return a string representation of this <code>X500Principal</code>
280      * using the specified format
281      * @throws IllegalArgumentException if the specified format is invalid
282      */

283     public String JavaDoc getName(String JavaDoc format) {
284     if (format != null) {
285         if (format.equalsIgnoreCase(RFC1779)) {
286         return thisX500Name.getRFC1779Name();
287         } else if (format.equalsIgnoreCase(RFC2253)) {
288         return thisX500Name.getRFC2253Name();
289         } else if (format.equalsIgnoreCase(CANONICAL)) {
290         return thisX500Name.getRFC2253CanonicalName();
291         }
292     }
293         throw new IllegalArgumentException JavaDoc("invalid format specified");
294     }
295
296     /**
297      * Returns the distinguished name in ASN.1 DER encoded form. The ASN.1
298      * notation for this structure is supplied in the documentation for
299      * {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
300      *
301      * <p>Note that the byte array returned is cloned to protect against
302      * subsequent modifications.
303      *
304      * @return a byte array containing the distinguished name in ASN.1 DER
305      * encoded form
306      */

307     public byte[] getEncoded() {
308     try {
309         return thisX500Name.getEncoded();
310     } catch (IOException e) {
311             throw new RuntimeException JavaDoc("unable to get encoding", e);
312     }
313     }
314
315     /**
316      * Return a user-friendly string representation of this
317      * <code>X500Principal</code>.
318      *
319      * @return a string representation of this <code>X500Principal</code>
320      */

321     public String JavaDoc toString() {
322     return thisX500Name.toString();
323     }
324
325     /**
326      * Compares the specified <code>Object</code> with this
327      * <code>X500Principal</code> for equality.
328      *
329      * <p> Specifically, this method returns <code>true</code> if
330      * the <code>Object</code> <i>o</i> is an <code>X500Principal</code>
331      * and if the respective canonical string representations
332      * (obtained via the <code>getName(X500Principal.CANONICAL)</code> method)
333      * of this object and <i>o</i> are equal.
334      *
335      * <p> This implementation is compliant with the requirements of RFC 2459.
336      *
337      * @param o Object to be compared for equality with this
338      * <code>X500Principal</code>
339      *
340      * @return <code>true</code> if the specified <code>Object</code> is equal
341      * to this <code>X500Principal</code>, <code>false</code> otherwise
342      */

343     public boolean equals(Object JavaDoc o) {
344         if (this == o) {
345             return true;
346     }
347     if (o instanceof X500Principal JavaDoc == false) {
348         return false;
349     }
350     X500Principal JavaDoc other = (X500Principal JavaDoc)o;
351     return this.thisX500Name.equals(other.thisX500Name);
352     }
353  
354     /**
355      * Return a hash code for this <code>X500Principal</code>.
356      *
357      * <p> The hash code is calculated via:
358      * <code>getName(X500Principal.CANONICAL).hashCode()</code>
359      *
360      * @return a hash code for this <code>X500Principal</code>
361      */

362     public int hashCode() {
363     return thisX500Name.hashCode();
364     }
365
366     /**
367      * Save the X500Principal object to a stream.
368      *
369      * @serialData this <code>X500Principal</code> is serialized
370      * by writing out its DER-encoded form
371      * (the value of <code>getEncoded</code> is serialized).
372      */

373     private void writeObject(java.io.ObjectOutputStream JavaDoc s)
374     throws IOException {
375     s.writeObject(thisX500Name.getEncodedInternal());
376     }
377
378     /**
379      * Reads this object from a stream (i.e., deserializes it).
380      */

381     private void readObject(java.io.ObjectInputStream JavaDoc s)
382     throws java.io.IOException JavaDoc,
383            java.io.NotActiveException JavaDoc,
384            ClassNotFoundException JavaDoc {
385
386     // re-create thisX500Name
387
thisX500Name = new X500Name((byte[])s.readObject());
388     }
389 }
390
Popular Tags