3261N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * This class represents a relative distinguished name, or RDN, which is a 0N/A * component of a distinguished name as specified by 0N/A * An example of an RDN is "OU=Sales+CN=J.Smith". In this example, 0N/A * the RDN consist of multiple attribute type/value pairs. The 0N/A * RDN is parsed as described in the class description for 0N/A * {@link javax.naming.ldap.LdapName <tt>LdapName</tt>}. 0N/A * The Rdn class represents an RDN as attribute type/value mappings, 0N/A * which can be viewed using 0N/A * {@link javax.naming.directory.Attributes Attributes}. 0N/A * In addition, it contains convenience methods that allow easy retrieval 0N/A * of type and value when the Rdn consist of a single type/value pair, 0N/A * which is how it appears in a typical usage. 0N/A * It also contains helper methods that allow escaping of the unformatted 0N/A * attribute value and unescaping of the value formatted according to the 0N/A * escaping syntax defined in RFC2253. For methods that take or return 0N/A * attribute value as an Object, the value is either a String 0N/A * (in unescaped form) or a byte array. 0N/A * <code>Rdn</code> will properly parse all valid RDNs, but 0N/A * does not attempt to detect all possible violations when parsing 0N/A * invalid RDNs. It is "generous" in accepting invalid RDNs. 0N/A * The "validity" of a name is determined ultimately when it 0N/A * is supplied to an LDAP server, which may accept or 0N/A * reject the name based on factors such as its schema information 0N/A * and interoperability considerations. 0N/A * The following code example shows how to construct an Rdn using the 0N/A * constructor that takes type and value as arguments: 0N/A * Rdn rdn = new Rdn("cn", "Juicy, Fruit"); 0N/A * System.out.println(rdn.toString()); 0N/A * The last line will print <tt>cn=Juicy\, Fruit</tt>. The 0N/A * {@link #unescapeValue(String) <tt>unescapeValue()</tt>} method can be 0N/A * used to unescape the escaped comma resulting in the original 0N/A * value <tt>"Juicy, Fruit"</tt>. The {@link #escapeValue(Object) 0N/A * <tt>escapeValue()</tt>} method adds the escape back preceding the comma. 0N/A * This class can be instantiated by a string representation 0N/A * of the RDN defined in RFC 2253 as shown in the following code example: 0N/A * Rdn rdn = new Rdn("cn=Juicy\\, Fruit"); 0N/A * System.out.println(rdn.toString()); 0N/A * The last line will print <tt>cn=Juicy\, Fruit</tt>. 0N/A * Concurrent multithreaded read-only access of an instance of 0N/A * <tt>Rdn</tt> need not be synchronized. 0N/A * Unless otherwise noted, the behavior of passing a null argument 0N/A * to a constructor or method in this class will cause NullPointerException 0N/A // private transient ArrayList<RdnEntry> entries; 0N/A * Constructs an Rdn from the given attribute set. See 0N/A * {@link javax.naming.directory.Attributes Attributes}. 0N/A * The string attribute values are not interpretted as 0N/A * formatted RDN strings. That is, the values are used 0N/A * literally (not parsed) and assumed to be unescaped. 0N/A * @param attrSet The non-null and non-empty attributes containing 0N/A * @throws InvalidNameException If contents of <tt>attrSet</tt> cannot 0N/A * be used to construct a valid RDN. 0N/A sort();
// arrange entries for comparison 0N/A * Constructs an Rdn from the given string. 0N/A * This constructor takes a string formatted according to the rules 0N/A * and described in the class description for 0N/A * {@link javax.naming.ldap.LdapName}. 0N/A * @param rdnString The non-null and non-empty RFC2253 formatted string. 0N/A * @throws InvalidNameException If a syntax error occurs during 0N/A * parsing of the rdnString. 0N/A * Constructs an Rdn from the given <tt>rdn</tt>. 0N/A * The contents of the <tt>rdn</tt> are simply copied into the newly 0N/A * @param rdn The non-null Rdn to be copied. 0N/A * Constructs an Rdn from the given attribute type and 0N/A * The string attribute values are not interpretted as 0N/A * formatted RDN strings. That is, the values are used 0N/A * literally (not parsed) and assumed to be unescaped. 0N/A * @param type The non-null and non-empty string attribute type. 0N/A * @param value The non-null and non-empty attribute value. 0N/A * @throws InvalidNameException If type/value cannot be used to 0N/A * construct a valid RDN. 0N/A "type or value cannot be empty, type:" +
type +
0N/A // An empty constructor used by the parser 0N/A * Adds the given attribute type and value to this Rdn. 0N/A * The string attribute values are not interpretted as 0N/A * formatted RDN strings. That is the values are used 0N/A * literally (not parsed) and assumed to be unescaped. 0N/A * @param type The non-null and non-empty string attribute type. 0N/A * @param value The non-null and non-empty attribute value. 0N/A * @return The updated Rdn, not a new one. Cannot be null. 0N/A if (
value instanceof byte[]) {
// clone the byte array 0N/A * Retrieves one of this Rdn's value. 0N/A * This is a convenience method for obtaining the value, 0N/A * when the RDN contains a single type and value mapping, 0N/A * which is the common RDN usage. 0N/A * For a multi-valued RDN, this method returns value corresponding 0N/A * to the type returned by {@link #getType() getType()} method. 0N/A * @return The non-null attribute value. 0N/A * Retrieves one of this Rdn's type. 0N/A * This is a convenience method for obtaining the type, 0N/A * when the RDN contains a single type and value mapping, 0N/A * which is the common RDN usage. 0N/A * no specific order defined on them. In that case, this method 0N/A * The {@link #getValue() getValue()} method returns the 0N/A * value corresponding to the type returned by this method. 0N/A * @return The non-null attribute type. 0N/A * Returns this Rdn as a string represented in a format defined by 0N/A * in the class description for {@link javax.naming.ldap.LdapName LdapName}. 0N/A * @return The string representation of the Rdn. 0N/A * Compares this Rdn with the specified Object for order. 0N/A * Returns a negative integer, zero, or a positive integer as this 0N/A * Rdn is less than, equal to, or greater than the given Object. 0N/A * If obj is null or not an instance of Rdn, ClassCastException 0N/A * The attribute type and value pairs of the RDNs are lined up 0N/A * against each other and compared lexicographically. The order of 0N/A * components in multi-valued Rdns (such as "ou=Sales+cn=Bob") is not 0N/A * @param obj The non-null object to compare against. 0N/A * @return A negative integer, zero, or a positive integer as this Rdn 0N/A * is less than, equal to, or greater than the given Object. 0N/A * @exception ClassCastException if obj is null or not a Rdn. 0N/A * Compares the specified Object with this Rdn for equality. 0N/A * Returns true if the given object is also a Rdn and the two Rdns 0N/A * represent the same attribute type and value mappings. The order of 0N/A * components in multi-valued Rdns (such as "ou=Sales+cn=Bob") is not 0N/A * Type and value equalilty matching is done as below: 0N/A * <li> The types are compared for equality with their case ignored. 0N/A * <li> String values with different but equivalent usage of quoting, 0N/A * escaping, or UTF8-hex-encoding are considered equal. 0N/A * The case of the values is ignored during the comparison. 0N/A * If obj is null or not an instance of Rdn, false is returned. 0N/A * @param obj object to be compared for equality with this Rdn. 0N/A * @return true if the specified object is equal to this Rdn. 0N/A * Returns the hash code of this RDN. Two RDNs that are 0N/A * equal (according to the equals method) will have the same 0N/A * @return An int representing the hash code of this Rdn. 0N/A // Sum up the hash codes of the components. 0N/A * Retrieves the {@link javax.naming.directory.Attributes Attributes} 0N/A * mappings of this Rdn. 0N/A // If non-null, a cannonical representation of the value suitable 0N/A // for comparison using String.compareTo() 0N/A // Any change here affecting equality must be 0N/A // reflected in hashCode(). 0N/A // Any change here must be reflected in hashCode() 0N/A * Retrieves the number of attribute type/value pairs in this Rdn. 0N/A * @return The non-negative number of type/value pairs in this Rdn. 0N/A * Given the value of an attribute, returns a string escaped according 0N/A * to the rules specified in 0N/A * For example, if the val is "Sue, Grabbit and Runn", the escaped 0N/A * value returned by this method is "Sue\, Grabbit and Runn". 0N/A * A string value is represented as a String and binary value 0N/A * @param val The non-null object to be escaped. 0N/A * @return Escaped string value. 0N/A * @throws ClassCastException if val is is not a String or byte array. 0N/A return (
val instanceof byte[])
0N/A * Given the value of a string-valued attribute, returns a 0N/A * string suitable for inclusion in a DN. This is accomplished by 0N/A * using backslash (\) to escape the following characters: 0N/A * leading and trailing whitespace 0N/A // Find leading and trailing whitespace. 0N/A int lead;
// index of first char that is not leading whitespace 0N/A int trail;
// index of last char that is not trailing whitespace 0N/A * Given the value of a binary attribute, returns a string 0N/A * suitable for inclusion in a DN (such as "#CEB1DF80"). 0N/A * TBD: This method should actually generate the ber encoding 0N/A * of the binary value 0N/A // return builder.toString().toUpperCase(); 0N/A * Given an attribute value string formated according to the rules 0N/A * returns the unformated value. Escapes and quotes are 0N/A * stripped away, and hex-encoded UTF-8 is converted to equivalent 0N/A * UTF-16 characters. Returns a string value as a String, and a 0N/A * binary value as a byte array. 0N/A * Legal and illegal values are defined in RFC 2253. 0N/A * This method is generous in accepting the values and does not 0N/A * catch all illegal values. 0N/A * Therefore, passing in an illegal value might not necessarily 0N/A * trigger an <tt>IllegalArgumentException</tt>. 0N/A * @param val The non-null string to be unescaped. 0N/A * @return Unescaped value. 0N/A * @throws IllegalArgumentException When an Illegal value 0N/A // Trim off leading and trailing whitespace. 0N/A // Add back the trailing whitespace with a preceeding '\' 0N/A // (escaped or unescaped) that was taken off in the above 0N/A // loop. Whether or not to retain this whitespace is decided below. 0N/A // Value is binary (eg: "#CEB1DF80"). 0N/A int esc = -
1;
// index of the last escaped character 0N/A ++i;
// skip backslash 0N/A // Convert hex-encoded UTF-8 to 16-bit chars. 0N/A }
else {
// no utf8 bytes available, invalid DN 0N/A // '/' has no meaning, throw exception 0N/A "Not a valid attribute string value:" +
0N/A val +
",improper usage of backslash");
0N/A // Get rid of the unescaped trailing whitespace with the 0N/A // preceeding '\' character that was previously added back. 0N/A * Given an array of chars (with starting and ending indexes into it) 0N/A * representing bytes encoded as hex-pairs (such as "CEB1DF80"), 0N/A * returns a byte array containing the decoded bytes. 0N/A * Given an array of chars (with starting and ending indexes into it), 0N/A * finds the largest prefix consisting of hex-encoded UTF-8 octets, 0N/A * and returns a byte array containing the corresponding UTF-8 octets. 0N/A * Hex-encoded UTF-8 octets look like this: 0N/A int len =
0;
// index of first unused byte in utf8 0N/A * Best guess as to what RFC 2253 means by "whitespace". 0N/A return (c ==
' ' || c ==
'\r');
0N/A * Serializes only the unparsed RDN, for compactness and to avoid 0N/A * any implementation dependency. 0N/A * @serialData The RDN string