2362N/A * Copyright (c) 2000, 2004, 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 * <tt>DnsName</tt> implements compound names for DNS as specified by 0N/A * RFCs 1034 and 1035, and as updated and clarified by RFCs 1123 and 2181. 0N/A * <p> The labels in a domain name correspond to JNDI atomic names. 0N/A * Each label must be less than 64 octets in length, and only the 0N/A * optional root label at the end of the name may be 0 octets long. 0N/A * The sum of the lengths of all labels in a name, plus the number of 0N/A * non-root labels plus 1, must be less than 256. The textual 0N/A * representation of a domain name consists of the labels, escaped as 0N/A * needed, dot-separated, and ordered right-to-left. 0N/A * <p> A label consists of a sequence of octets, each of which may 0N/A * have any value from 0 to 255. 0N/A * <p> <em>Host names</em> are a subset of domain names. 0N/A * Their labels contain only ASCII letters, digits, and hyphens, and 0N/A * none may begin or end with a hyphen. While names not conforming to 0N/A * these rules may be valid domain names, they will not be usable by a 0N/A * number of DNS applications, and should in most cases be avoided. 0N/A * <p> DNS does not specify an encoding (such as UTF-8) to use for 0N/A * octets with non-ASCII values. As of this writing there is some 0N/A * work going on in this area, but it is not yet finalized. 0N/A * <tt>DnsName</tt> currently converts any non-ASCII octets into 0N/A * characters using ISO-LATIN-1 encoding, in effect taking the 0N/A * value of each octet and storing it directly into the low-order byte 0N/A * of a Java character and <i>vice versa</i>. As a consequence, no 0N/A * character in a DNS name will ever have a non-zero high-order byte. 0N/A * When the work on internationalizing domain names has stabilized 0N/A * may be updated to conform to that work. 0N/A * <p> Backslash (<tt>\</tt>) is used as the escape character in the 0N/A * textual representation of a domain name. The character sequence 0N/A * `<tt>\DDD</tt>', where <tt>DDD</tt> is a 3-digit decimal number 0N/A * (with leading zeros if needed), represents the octet whose value 0N/A * is <tt>DDD</tt>. The character sequence `<tt>\C</tt>', where 0N/A * <tt>C</tt> is a character other than <tt>'0'</tt> through 0N/A * <tt>'9'</tt>, represents the octet whose value is that of 0N/A * <tt>C</tt> (again using ISO-LATIN-1 encoding); this is particularly 0N/A * useful for escaping <tt>'.'</tt> or backslash itself. Backslash is 0N/A * otherwise not allowed in a domain name. Note that escape characters 0N/A * are interpreted when a name is parsed. So, for example, the character 0N/A * sequences `<tt>S</tt>', `<tt>\S</tt>', and `<tt>\083</tt>' each 0N/A * represent the same one-octet name. The <tt>toString()</tt> method 0N/A * does not generally insert escape sequences except where necessary. 0N/A * If, however, the <tt>DnsName</tt> was constructed using unneeded 0N/A * escapes, those escapes may appear in the <tt>toString</tt> result. 0N/A * <p> Atomic names passed as parameters to methods of 0N/A * <tt>DnsName</tt>, and those returned by them, are unescaped. So, 0N/A * for example, <tt>(new DnsName()).add("a.b")</tt> creates an 0N/A * object representing the one-label domain name <tt>a\.b</tt>, and 0N/A * calling <tt>get(0)</tt> on this object returns <tt>"a.b"</tt>. 0N/A * <p> While DNS names are case-preserving, comparisons between them 0N/A * are case-insensitive. When comparing names containing non-ASCII 0N/A * octets, <tt>DnsName</tt> uses case-insensitive comparison 0N/A * between pairs of ASCII values, and exact binary comparison 0N/A * <p> A <tt>DnsName</tt> instance is not synchronized against 0N/A * concurrent access by multiple threads. 0N/A * @author Scott Seligman 0N/A // If non-null, the domain name represented by this DnsName. 0N/A // The labels of this domain name, as a list of strings. Index 0 0N/A // corresponds to the leftmost (least significant) label: note that 0N/A // this is the reverse of the ordering used by the Name interface. 0N/A // The number of octets needed to carry this domain name in a DNS 0N/A // packet. Equal to the sum of the lengths of each label, plus the 0N/A // number of non-root labels, plus 1. Must remain less than 256. 0N/A * Constructs a <tt>DnsName</tt> representing the empty domain name. 0N/A * Constructs a <tt>DnsName</tt> representing a given domain name. 0N/A * @param name the domain name to parse 0N/A * @throws InvalidNameException if <tt>name</tt> does not conform 0N/A * Returns a new DnsName with its name components initialized to 0N/A * the components of "n" in the range [beg,end). Indexing is as 0N/A * for the Name interface, with 0 being the most significant. 0N/A // Compute indexes into "labels", which has least-significant label 0N/A // at index 0 (opposite to the convention used for "beg" and "end"). 0N/A * Does this domain name follow <em>host name</em> syntax? 0N/A return ((
size() == n.
size()) &&
// shortcut: do sizes differ? 0N/A int i =
size() -
pos -
1;
// index of "pos" component in "labels" 0N/A int i =
size() -
pos -
1;
// index of element to remove in "labels" 0N/A // Check for empty labels: may have only one, and only at end. 0N/A "Empty label must be the last label in a domain name");
0N/A // Check total name length. 0N/A int i =
size() -
pos;
// index for insertion into "labels" 0N/A // "n" is a DnsName so we can insert it as a whole, rather than 0N/A // verifying and inserting it component-by-component. 0N/A // More code, but less work. 0N/A // Check for empty labels: may have only one, and only at end. 0N/A "Empty label must be the last label in a domain name");
0N/A int i =
size() -
pos;
// index for insertion into "labels" 0N/A // Preserve "domain" if we're appending or prepending, 0N/A // otherwise invalidate it. 0N/A }
else {
// "n" is a compound name, but not a DnsName. 0N/A // Add labels least-significant first: sometimes more efficient. 0N/A for (
int i = n.
size() -
1; i >=
0; i--) {
0N/A * Helper method for public comparison methods. Lexicographically 0N/A * compares components of this name in the range [beg,end) with 0N/A * all components of "n". Indexing is as for the Name interface, 0N/A * with 0 being the most significant. Returns negative, zero, or 0N/A * positive as these name components are less than, equal to, or 0N/A * greater than those of "n". 0N/A // Loop through labels, starting with most significant. 0N/A int j =
size() - (i +
beg) -
1;
// index of label1 in "labels" 0N/A // assert (label1 == labels.get(j)); 0N/A * Returns a key suitable for hashing the label at index i. 0N/A * Indexing is as for the Name interface, with 0 being the most 0N/A * Parses a domain name, setting the values of instance vars accordingly. 0N/A if (c ==
'\\') {
// found an escape sequence 0N/A i +=
2;
// consume remaining digits 0N/A }
else if (c !=
'.') {
// an unescaped octet 0N/A }
else {
// found '.' separator 0N/A // If name is neither "." nor "", the octets (zero or more) 0N/A // from the rightmost dot onward are now added as the final 0N/A // label of the name. Those two are special cases in that for 0N/A // all other domain names, the number of labels is one greater 0N/A // than the number of dot separators. 0N/A * Returns (as a char) the octet indicated by the escape sequence 0N/A * at a given position within a domain name. 0N/A * @throws InvalidNameException if a valid escape sequence is not found. 0N/A // assert (name.charAt(pos) == '\\'); 0N/A ((
c1 -
'0') *
100 + (
c2 -
'0') *
10 + (
c3 -
'0'));
0N/A "Invalid escape sequence in " +
name);
0N/A }
else {
// sequence is `\C' 0N/A "Invalid escape sequence in " +
name);
0N/A * Checks that this label is valid. 0N/A * @throws InvalidNameException if label is not valid. 0N/A // Check for two-byte characters. 0N/A if ((c &
0xFF00) !=
0) {
0N/A * Does this label conform to host name syntax? 0N/A c >=
'a' && c <=
'z' ||
0N/A c >=
'A' && c <=
'Z' ||
0N/A c >=
'0' && c <=
'9');
0N/A return (c >=
'0' && c <=
'9');
0N/A * Append a label to buf, escaping as needed. 0N/A if (c ==
'.' || c ==
'\\') {
0N/A * Compares two labels, ignoring case for ASCII values. 0N/A * Returns negative, zero, or positive as the first label 0N/A * is less than, equal to, or greater than the second. 0N/A * See keyForLabel(). 0N/A for (
int i =
0; i <
min; i++) {
0N/A c1 +=
'a' -
'A';
// to lower case 0N/A c2 +=
'a' -
'A';
// to lower case 0N/A * Returns a key suitable for hashing a label. Two labels map to 0N/A * the same key iff they are equal, taking possible case-folding 0N/A * into account. See compareLabels(). 0N/A if (c >=
'A' && c <=
'Z') {
0N/A c +=
'a' -
'A';
// to lower case 0N/A * Serializes only the domain name string, for compactness and to avoid 0N/A * any implementation dependency. 0N/A * @serialdata The domain name string.