rdn.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 463 行

JAVA
463
字号
/* * @(#)RDN.java	1.6 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */package sun.security.x509;import java.lang.reflect.*;import java.io.IOException;import java.io.StringReader;import java.security.PrivilegedExceptionAction;import java.security.AccessController;import java.security.Principal;import java.util.*;import sun.security.util.*;import sun.security.pkcs.PKCS9Attribute;import javax.security.auth.x500.X500Principal;/** * RDNs are a set of {attribute = value} assertions.  Some of those * attributes are "distinguished" (unique w/in context).  Order is * never relevant. * * Some X.500 names include only a single distinguished attribute * per RDN.  This style is currently common. * * Note that DER-encoded RDNs sort AVAs by assertion OID ... so that * when we parse this data we don't have to worry about canonicalizing * it, but we'll need to sort them when we expose the RDN class more. * <p> * The ASN.1 for RDNs is: * <pre> * RelativeDistinguishedName ::= *   SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { *   type     AttributeType, *   value    AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * </pre> * * Note that instances of this class are immutable. * * @version 1.6, 10/10/06 */public class RDN {    // currently not private, accessed directly from X500Name    final AVA[] assertion;        // cached immutable List of the AVAs    private volatile List avaList;        // cache canonical String form    private volatile String canonicalString;    /**     * Constructs an RDN from its printable representation.      *     * An RDN may consist of one or multiple Attribute Value Assertions (AVAs),     * using '+' as a separator.     * If the '+' should be considered part of an AVA value, it must be     * preceded by '\'.     *     * @param name String form of RDN     * @throws IOException on parsing error     */    public RDN(String name) throws IOException {        int quoteCount = 0;        int searchOffset = 0;	int avaOffset = 0;	Vector avaVec = new Vector(3);	int nextPlus = name.indexOf('+');	while (nextPlus >= 0) {	    quoteCount += X500Name.countQuotes(name, searchOffset, nextPlus);            /*             * We have encountered an AVA delimiter (plus sign).             * If the plus sign in the RDN under consideration is             * preceded by a backslash (escape), or by a double quote, it             * is part of the AVA. Otherwise, it is used as a separator, to 	     * delimit the AVA under consideration from any subsequent AVAs.             */	    if (nextPlus > 0 && name.charAt(nextPlus - 1) != '\\'	        && quoteCount != 1) {                /*                 * Plus sign is a separator                 */                String avaString = name.substring(avaOffset, nextPlus);	        if (avaString.length() == 0) {		    throw new IOException("empty AVA in RDN \"" + name + "\"");		}                // Parse AVA, and store it in vector                AVA ava = new AVA(new StringReader(avaString));                avaVec.addElement(ava);                // Increase the offset                avaOffset = nextPlus + 1;                // Set quote counter back to zero                quoteCount = 0;	    }            searchOffset = nextPlus + 1;	    nextPlus = name.indexOf('+', searchOffset);        }        // parse last or only AVA        String avaString = name.substring(avaOffset);        if (avaString.length() == 0) {	    throw new IOException("empty AVA in RDN \"" + name + "\"");        }        AVA ava = new AVA(new StringReader(avaString));        avaVec.addElement(ava);        assertion = (AVA[]) avaVec.toArray(new AVA[avaVec.size()]);    }    /*     * Constructs an RDN from its printable representation.      *     * An RDN may consist of one or multiple Attribute Value Assertions (AVAs),     * using '+' as a separator.     * If the '+' should be considered part of an AVA value, it must be     * preceded by '\'.     *     * @param name String form of RDN     * @throws IOException on parsing error     */    RDN(String name, String format) throws IOException {        if (format.equalsIgnoreCase("RFC2253") == false) {	    throw new IOException("Unsupported format " + format);	}        int searchOffset = 0;	int avaOffset = 0;	Vector avaVec = new Vector(3);	int nextPlus = name.indexOf('+');	while (nextPlus >= 0) {            /*             * We have encountered an AVA delimiter (plus sign).             * If the plus sign in the RDN under consideration is             * preceded by a backslash (escape), or by a double quote, it             * is part of the AVA. Otherwise, it is used as a separator, to 	     * delimit the AVA under consideration from any subsequent AVAs.             */	    if (nextPlus > 0 && name.charAt(nextPlus - 1) != '\\' ) {                /*                 * Plus sign is a separator                 */                String avaString = name.substring(avaOffset, nextPlus);	        if (avaString.length() == 0) {		    throw new IOException("empty AVA in RDN \"" + name + "\"");		}                // Parse AVA, and store it in vector                AVA ava = new AVA(new StringReader(avaString), AVA.RFC2253);                avaVec.addElement(ava);                // Increase the offset                avaOffset = nextPlus + 1;	    }            searchOffset = nextPlus + 1;	    nextPlus = name.indexOf('+', searchOffset);        }        // parse last or only AVA        String avaString = name.substring(avaOffset);        if (avaString.length() == 0) {	    throw new IOException("empty AVA in RDN \"" + name + "\"");        }        AVA ava = new AVA(new StringReader(avaString), AVA.RFC2253);        avaVec.addElement(ava);        assertion = (AVA[]) avaVec.toArray(new AVA[avaVec.size()]);    }    /*     * Constructs an RDN from an ASN.1 encoded value.  The encoding     * of the name in the stream uses DER (a BER/1 subset).     *     * @param value a DER-encoded value holding an RDN.     * @throws IOException on parsing error.     */    RDN(DerValue rdn) throws IOException {	if (rdn.tag != DerValue.tag_Set) {	    throw new IOException("X500 RDN");	}	DerInputStream dis = new DerInputStream(rdn.toByteArray());	DerValue[] avaset = dis.getSet(5);	assertion = new AVA[avaset.length];	for (int i = 0; i < avaset.length; i++) {	    assertion[i] = new AVA(avaset[i]);	}    }    /*     * Creates an empty RDN with slots for specified     * number of AVAs.     *     * @param i number of AVAs to be in RDN     */    RDN(int i) { assertion = new AVA[i]; }        public RDN(AVA ava) {	if (ava == null) {	    throw new NullPointerException();	}	assertion = new AVA[] { ava };    }        public RDN(AVA[] avas) {	assertion = (AVA[])avas.clone();	for (int i = 0; i < assertion.length; i++) {	    if (assertion[i] == null) {		throw new NullPointerException();	    }	}    }        /**     * Return an immutable List of the AVAs in this RDN.     */    public List avas() {	List list = avaList;	if (list == null) {	    list = Collections.unmodifiableList(Arrays.asList(assertion));	    avaList = list;	}	return list;    }        /**     * Return the number of AVAs in this RDN.     */    public int size() {	return assertion.length;    }    public boolean equals(Object obj) {	if (this == obj) {	    return true;	}	if (obj instanceof RDN == false) {	    return false;	}	RDN other = (RDN)obj;	if (this.assertion.length != other.assertion.length) {	    return false;	}	String thisCanon = this.toRFC2253String(true);	String otherCanon = other.toRFC2253String(true);	return thisCanon.equals(otherCanon);    }        /*     * Calculates a hash code value for the object.  Objects     * which are equal will also have the same hashcode.     *     * @returns int hashCode value     */    public int hashCode() {	return toRFC2253String(true).hashCode();    }    /*     * return specified attribute value from RDN     *     * @params oid ObjectIdentifier of attribute to be found     * @returns DerValue of attribute value; null if attribute does not exist     */    DerValue findAttribute(ObjectIdentifier oid) {	for (int i = 0; i < assertion.length; i++) {	    if (assertion[i].oid.equals(oid)) {		return assertion[i].value;	    }	}	return null;    }    /*     * Encode the RDN in DER-encoded form.     *     * @param out DerOutputStream to which RDN is to be written     * @throws IOException on error     */    void encode(DerOutputStream out) throws IOException {	out.putOrderedSetOf(DerValue.tag_Set, assertion);    }    /*     * Returns a printable form of this RDN, using RFC 1779 style catenation     * of attribute/value assertions, and emitting attribute type keywords     * from RFC 1779, 2253, and 2459.     */    public String toString() {	if (assertion.length == 1) {	    return assertion[0].toString();	}		StringBuffer sb = new StringBuffer();	for (int i = 0; i < assertion.length; i++) {	    if (i != 0) {		sb.append(" + ");	    }	    sb.append(assertion[i].toString());	}	return sb.toString();    }    /*     * Returns a printable form of this RDN using the algorithm defined in     * RFC 1779. Only RFC 1779 attribute type keywords are emitted.     */    public String toRFC1779String() {	if (assertion.length == 1) {	    return assertion[0].toRFC1779String();	}	StringBuffer sb = new StringBuffer();	for (int i = 0; i < assertion.length; i++) {	    if (i != 0) {		sb.append(" + ");	    }	    sb.append(assertion[i].toRFC1779String());	}	return sb.toString();    }    /*     * Returns a printable form of this RDN using the algorithm defined in     * RFC 2253. Only RFC 2253 attribute type keywords are emitted.     */    public String toRFC2253String() {	return toRFC2253StringInternal(false);    }    /*     * Returns a printable form of this RDN using the algorithm defined in     * RFC 2253. Only RFC 2253 attribute type keywords are emitted.     * If canonical is true, then additional canonicalizations     * documented in X500Principal.getName are performed.     */    public String toRFC2253String(boolean canonical) {	if (canonical == false) {	    return toRFC2253StringInternal(false);	}	String c = canonicalString;	if (c == null) {	    c = toRFC2253StringInternal(true);	    canonicalString = c;	}	return c;    }        private String toRFC2253StringInternal(boolean canonical) {	/*	 * Section 2.2: When converting from an ASN.1 RelativeDistinguishedName 	 * to a string, the output consists of the string encodings of each 	 * AttributeTypeAndValue (according to 2.3), in any order.	 *   	 * Where there is a multi-valued RDN, the outputs from adjoining   	 * AttributeTypeAndValues are separated by a plus ('+' ASCII 43)   	 * character.	 */	 	// normally, an RDN only contains one AVA	if (assertion.length == 1) {	    return canonical ? assertion[0].toRFC2253CanonicalString() : 	    		       assertion[0].toRFC2253String();	}	StringBuffer relname = new StringBuffer();	if (!canonical) {	    for (int i = 0; i < assertion.length; i++) {		if (i > 0) {		    relname.append('+');		}		relname.append(assertion[i].toRFC2253String());	    }	} else {	    // order the string type AVA's alphabetically,	    // followed by the oid type AVA's numerically	    List avaList = new ArrayList(assertion.length);	    for (int i = 0; i < assertion.length; i++) {		avaList.add(assertion[i]);	    }	    java.util.Collections.sort(avaList, AVAComparator.getInstance());	    for (int i = 0; i < avaList.size(); i++) {		if (i > 0) {		    relname.append('+');		}		relname.append		    (((AVA)avaList.get(i)).toRFC2253CanonicalString());	    }	}	return new String(relname);    }}class AVAComparator implements Comparator {        private static final Comparator INSTANCE = new AVAComparator();        private AVAComparator() {	// empty    }        static Comparator getInstance() {	return INSTANCE;    }        /**     * AVA's containing a standard keyword are ordered alphabetically,     * followed by AVA's containing an OID keyword, ordered numerically     */    public int compare(Object o1, Object o2) {	AVA a1 = (AVA)o1;	AVA a2 = (AVA)o2;		boolean a1Has2253 = a1.hasRFC2253Keyword();	boolean a2Has2253 = a2.hasRFC2253Keyword();	if (a1Has2253 == a2Has2253) {	    return a1.toRFC2253CanonicalString().compareTo			(a2.toRFC2253CanonicalString());	} else {	    if (a1Has2253) {		return -1;	    } else {		return 1;	    }	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?