001/* 002 * Copyright (C) 2009 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.net; 016 017import static com.google.common.base.Preconditions.checkArgument; 018import static com.google.common.base.Preconditions.checkNotNull; 019import static com.google.common.base.Preconditions.checkState; 020 021import com.google.common.annotations.GwtCompatible; 022import com.google.common.base.Ascii; 023import com.google.common.base.CharMatcher; 024import com.google.common.base.Splitter; 025import com.google.common.collect.ImmutableList; 026import com.google.errorprone.annotations.CanIgnoreReturnValue; 027import com.google.errorprone.annotations.Immutable; 028import com.google.errorprone.annotations.concurrent.LazyInit; 029import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; 030import com.google.thirdparty.publicsuffix.PublicSuffixType; 031import java.util.List; 032import org.jspecify.annotations.Nullable; 033 034/** 035 * An immutable well-formed internet domain name, such as {@code com} or {@code foo.co.uk}. Only 036 * syntactic analysis is performed; no DNS lookups or other network interactions take place. Thus 037 * there is no guarantee that the domain actually exists on the internet. 038 * 039 * <p>One common use of this class is to determine whether a given string is likely to represent an 040 * addressable domain on the web -- that is, for a candidate string {@code "xxx"}, might browsing to 041 * {@code "http://xxx/"} result in a webpage being displayed? In the past, this test was frequently 042 * done by determining whether the domain ended with a {@linkplain #isPublicSuffix() public suffix} 043 * but was not itself a public suffix. However, this test is no longer accurate. There are many 044 * domains which are both public suffixes and addressable as hosts; {@code "uk.com"} is one example. 045 * Using the subset of public suffixes that are {@linkplain #isRegistrySuffix() registry suffixes}, 046 * one can get a better result, as only a few registry suffixes are addressable. However, the most 047 * useful test to determine if a domain is a plausible web host is {@link #hasPublicSuffix()}. This 048 * will return {@code true} for many domains which (currently) are not hosts, such as {@code "com"}, 049 * but given that any public suffix may become a host without warning, it is better to err on the 050 * side of permissiveness and thus avoid spurious rejection of valid sites. Of course, to actually 051 * determine addressability of any host, clients of this class will need to perform their own DNS 052 * lookups. 053 * 054 * <p>During construction, names are normalized in two ways: 055 * 056 * <ol> 057 * <li>ASCII uppercase characters are converted to lowercase. 058 * <li>Unicode dot separators other than the ASCII period ({@code '.'}) are converted to the ASCII 059 * period. 060 * </ol> 061 * 062 * <p>The normalized values will be returned from {@link #toString()} and {@link #parts()}, and will 063 * be reflected in the result of {@link #equals(Object)}. 064 * 065 * <p><a href="http://en.wikipedia.org/wiki/Internationalized_domain_name">Internationalized domain 066 * names</a> such as {@code 网络.cn} are supported, as are the equivalent <a 067 * href="http://en.wikipedia.org/wiki/Internationalized_domain_name">IDNA Punycode-encoded</a> 068 * versions. 069 * 070 * @author Catherine Berry 071 * @since 5.0 072 */ 073@GwtCompatible 074@Immutable 075public final class InternetDomainName { 076 077 private static final CharMatcher DOTS_MATCHER = CharMatcher.anyOf(".\u3002\uFF0E\uFF61"); 078 private static final Splitter DOT_SPLITTER = Splitter.on('.'); 079 080 /** 081 * Value of {@link #publicSuffixIndex()} or {@link #registrySuffixIndex()} which indicates that no 082 * relevant suffix was found. 083 */ 084 private static final int NO_SUFFIX_FOUND = -1; 085 086 /** 087 * Value of {@link #publicSuffixIndexCache} or {@link #registrySuffixIndexCache} which indicates 088 * that they were not initialized yet. 089 */ 090 private static final int SUFFIX_NOT_INITIALIZED = -2; 091 092 /** 093 * Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described 094 * in <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11 with the fact that the 095 * encoding of each part occupies at least two bytes (dot plus label externally, length byte plus 096 * label internally). Thus, if all labels have the minimum size of one byte, 127 of them will fit. 097 */ 098 private static final int MAX_PARTS = 127; 099 100 /** 101 * Maximum length of a full domain name, including separators, and leaving room for the root 102 * label. See <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11. 103 */ 104 private static final int MAX_LENGTH = 253; 105 106 /** 107 * Maximum size of a single part of a domain name. See <a 108 * href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11. 109 */ 110 private static final int MAX_DOMAIN_PART_LENGTH = 63; 111 112 /** The full domain name, converted to lower case. */ 113 private final String name; 114 115 /** The parts of the domain name, converted to lower case. */ 116 private final ImmutableList<String> parts; 117 118 /** 119 * Cached value of #publicSuffixIndex(). Do not use directly. 120 * 121 * <p>Since this field isn't {@code volatile}, if an instance of this class is shared across 122 * threads before it is initialized, then each thread is likely to compute their own copy of the 123 * value. 124 */ 125 @SuppressWarnings("Immutable") 126 @LazyInit 127 private int publicSuffixIndexCache = SUFFIX_NOT_INITIALIZED; 128 129 /** 130 * Cached value of #registrySuffixIndex(). Do not use directly. 131 * 132 * <p>Since this field isn't {@code volatile}, if an instance of this class is shared across 133 * threads before it is initialized, then each thread is likely to compute their own copy of the 134 * value. 135 */ 136 @SuppressWarnings("Immutable") 137 @LazyInit 138 private int registrySuffixIndexCache = SUFFIX_NOT_INITIALIZED; 139 140 /** Constructor used to implement {@link #from(String)}, and from subclasses. */ 141 InternetDomainName(String name) { 142 // Normalize: 143 // * ASCII characters to lowercase 144 // * All dot-like characters to '.' 145 // * Strip trailing '.' 146 147 name = Ascii.toLowerCase(DOTS_MATCHER.replaceFrom(name, '.')); 148 149 if (name.endsWith(".")) { 150 name = name.substring(0, name.length() - 1); 151 } 152 153 checkArgument(name.length() <= MAX_LENGTH, "Domain name too long: '%s':", name); 154 this.name = name; 155 156 this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); 157 checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); 158 checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); 159 } 160 161 /** 162 * Internal constructor that skips validations when creating an instance from parts of an 163 * already-validated InternetDomainName, as in {@link ancestor}. 164 */ 165 private InternetDomainName(String name, ImmutableList<String> parts) { 166 checkArgument(!parts.isEmpty(), "Cannot create an InternetDomainName with zero parts."); 167 this.name = name; 168 this.parts = parts; 169 } 170 171 /** 172 * The index in the {@link #parts()} list at which the public suffix begins. For example, for the 173 * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code 174 * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public 175 * suffix was found. 176 */ 177 private int publicSuffixIndex() { 178 int publicSuffixIndexLocal = publicSuffixIndexCache; 179 if (publicSuffixIndexLocal == SUFFIX_NOT_INITIALIZED) { 180 publicSuffixIndexCache = 181 publicSuffixIndexLocal = PublicSuffixPatterns.TRIE.findSuffixIndex(parts); 182 } 183 return publicSuffixIndexLocal; 184 } 185 186 /** 187 * The index in the {@link #parts()} list at which the registry suffix begins. For example, for 188 * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code 189 * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix 190 * was found. 191 */ 192 private int registrySuffixIndex() { 193 int registrySuffixIndexLocal = registrySuffixIndexCache; 194 if (registrySuffixIndexLocal == SUFFIX_NOT_INITIALIZED) { 195 registrySuffixIndexCache = 196 registrySuffixIndexLocal = 197 PublicSuffixPatterns.TRIE.findSuffixIndex(parts, PublicSuffixType.REGISTRY); 198 } 199 return registrySuffixIndexLocal; 200 } 201 202 /** 203 * Returns an instance of {@link InternetDomainName} after lenient validation. Specifically, 204 * validation against <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a> 205 * ("Internationalizing Domain Names in Applications") is skipped, while validation against <a 206 * href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: 207 * 208 * <ul> 209 * <li>Any part containing non-ASCII characters is considered valid. 210 * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. 211 * <li>Parts other than the final part may start with a digit, as mandated by <a 212 * href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. 213 * </ul> 214 * 215 * @param domain A domain name (not IP address) 216 * @throws IllegalArgumentException if {@code domain} is not syntactically valid according to 217 * {@link #isValid} 218 * @since 10.0 (previously named {@code fromLenient}) 219 */ 220 @CanIgnoreReturnValue // TODO(b/219820829): consider removing 221 public static InternetDomainName from(String domain) { 222 return new InternetDomainName(checkNotNull(domain)); 223 } 224 225 /** 226 * Validation method used by {@code from} to ensure that the domain name is syntactically valid 227 * according to RFC 1035. 228 * 229 * @return Is the domain name syntactically valid? 230 */ 231 private static boolean validateSyntax(List<String> parts) { 232 int lastIndex = parts.size() - 1; 233 234 // Validate the last part specially, as it has different syntax rules. 235 236 if (!validatePart(parts.get(lastIndex), true)) { 237 return false; 238 } 239 240 for (int i = 0; i < lastIndex; i++) { 241 String part = parts.get(i); 242 if (!validatePart(part, false)) { 243 return false; 244 } 245 } 246 247 return true; 248 } 249 250 private static final CharMatcher DASH_MATCHER = CharMatcher.anyOf("-_"); 251 252 private static final CharMatcher DIGIT_MATCHER = CharMatcher.inRange('0', '9'); 253 254 private static final CharMatcher LETTER_MATCHER = 255 CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')); 256 257 private static final CharMatcher PART_CHAR_MATCHER = 258 DIGIT_MATCHER.or(LETTER_MATCHER).or(DASH_MATCHER); 259 260 /** 261 * Helper method for {@link #validateSyntax(List)}. Validates that one part of a domain name is 262 * valid. 263 * 264 * @param part The domain name part to be validated 265 * @param isFinalPart Is this the final (rightmost) domain part? 266 * @return Whether the part is valid 267 */ 268 private static boolean validatePart(String part, boolean isFinalPart) { 269 270 // These tests could be collapsed into one big boolean expression, but 271 // they have been left as independent tests for clarity. 272 273 if (part.length() < 1 || part.length() > MAX_DOMAIN_PART_LENGTH) { 274 return false; 275 } 276 277 /* 278 * GWT claims to support java.lang.Character's char-classification methods, but it actually only 279 * works for ASCII. So for now, assume any non-ASCII characters are valid. The only place this 280 * seems to be documented is here: 281 * https://groups.google.com/d/topic/google-web-toolkit-contributors/1UEzsryq1XI 282 * 283 * <p>ASCII characters in the part are expected to be valid per RFC 1035, with underscore also 284 * being allowed due to widespread practice. 285 */ 286 287 String asciiChars = CharMatcher.ascii().retainFrom(part); 288 289 if (!PART_CHAR_MATCHER.matchesAllOf(asciiChars)) { 290 return false; 291 } 292 293 // No initial or final dashes or underscores. 294 295 if (DASH_MATCHER.matches(part.charAt(0)) 296 || DASH_MATCHER.matches(part.charAt(part.length() - 1))) { 297 return false; 298 } 299 300 /* 301 * Note that we allow (in contravention of a strict interpretation of the relevant RFCs) domain 302 * parts other than the last may begin with a digit (for example, "3com.com"). It's important to 303 * disallow an initial digit in the last part; it's the only thing that stops an IPv4 numeric 304 * address like 127.0.0.1 from looking like a valid domain name. 305 */ 306 307 if (isFinalPart && DIGIT_MATCHER.matches(part.charAt(0))) { 308 return false; 309 } 310 311 return true; 312 } 313 314 /** 315 * Returns the individual components of this domain name, normalized to all lower case. For 316 * example, for the domain name {@code mail.google.com}, this method returns the list {@code 317 * ["mail", "google", "com"]}. 318 */ 319 public ImmutableList<String> parts() { 320 return parts; 321 } 322 323 /** 324 * Indicates whether this domain name represents a <i>public suffix</i>, as defined by the Mozilla 325 * Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A public suffix 326 * is one under which Internet users can directly register names, such as {@code com}, {@code 327 * co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public suffixes 328 * include {@code google.com}, {@code foo.co.uk}, and {@code myblog.blogspot.com}. 329 * 330 * <p>Public suffixes are a proper superset of {@linkplain #isRegistrySuffix() registry suffixes}. 331 * The list of public suffixes additionally contains privately owned domain names under which 332 * Internet users can register subdomains. An example of a public suffix that is not a registry 333 * suffix is {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> 334 * registry suffixes, since domain name registries collectively control all internet domain names. 335 * 336 * <p>For considerations on whether the public suffix or registry suffix designation is more 337 * suitable for your application, see <a 338 * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. 339 * 340 * @return {@code true} if this domain name appears exactly on the public suffix list 341 * @since 6.0 342 */ 343 public boolean isPublicSuffix() { 344 return publicSuffixIndex() == 0; 345 } 346 347 /** 348 * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, 349 * including if it is a public suffix itself. For example, returns {@code true} for {@code 350 * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code 351 * google.invalid}. This is the recommended method for determining whether a domain is potentially 352 * an addressable host. 353 * 354 * <p>Note that this method is equivalent to {@link #hasRegistrySuffix()} because all registry 355 * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. 356 * 357 * @since 6.0 358 */ 359 public boolean hasPublicSuffix() { 360 return publicSuffixIndex() != NO_SUFFIX_FOUND; 361 } 362 363 /** 364 * Returns the {@linkplain #isPublicSuffix() public suffix} portion of the domain name, or {@code 365 * null} if no public suffix is present. 366 * 367 * @since 6.0 368 */ 369 public @Nullable InternetDomainName publicSuffix() { 370 return hasPublicSuffix() ? ancestor(publicSuffixIndex()) : null; 371 } 372 373 /** 374 * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, 375 * while not being a public suffix itself. For example, returns {@code true} for {@code 376 * www.google.com}, {@code foo.co.uk} and {@code myblog.blogspot.com}, but not for {@code com}, 377 * {@code co.uk}, {@code google.invalid}, or {@code blogspot.com}. 378 * 379 * <p>This method can be used to determine whether it will probably be possible to set cookies on 380 * the domain, though even that depends on individual browsers' implementations of cookie 381 * controls. See <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> for details. 382 * 383 * @since 6.0 384 */ 385 public boolean isUnderPublicSuffix() { 386 return publicSuffixIndex() > 0; 387 } 388 389 /** 390 * Indicates whether this domain name is composed of exactly one subdomain component followed by a 391 * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for {@code 392 * google.com} {@code foo.co.uk}, and {@code myblog.blogspot.com}, but not for {@code 393 * www.google.com}, {@code co.uk}, or {@code blogspot.com}. 394 * 395 * <p>This method can be used to determine whether a domain is probably the highest level for 396 * which cookies may be set, though even that depends on individual browsers' implementations of 397 * cookie controls. See <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> for details. 398 * 399 * @since 6.0 400 */ 401 public boolean isTopPrivateDomain() { 402 return publicSuffixIndex() == 1; 403 } 404 405 /** 406 * Returns the portion of this domain name that is one level beneath the {@linkplain 407 * #isPublicSuffix() public suffix}. For example, for {@code x.adwords.google.co.uk} it returns 408 * {@code google.co.uk}, since {@code co.uk} is a public suffix. Similarly, for {@code 409 * myblog.blogspot.com} it returns the same domain, {@code myblog.blogspot.com}, since {@code 410 * blogspot.com} is a public suffix. 411 * 412 * <p>If {@link #isTopPrivateDomain()} is true, the current domain name instance is returned. 413 * 414 * <p>This method can be used to determine the probable highest level parent domain for which 415 * cookies may be set, though even that depends on individual browsers' implementations of cookie 416 * controls. 417 * 418 * @throws IllegalStateException if this domain does not end with a public suffix 419 * @since 6.0 420 */ 421 public InternetDomainName topPrivateDomain() { 422 if (isTopPrivateDomain()) { 423 return this; 424 } 425 checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); 426 return ancestor(publicSuffixIndex() - 1); 427 } 428 429 /** 430 * Indicates whether this domain name represents a <i>registry suffix</i>, as defined by a subset 431 * of the Mozilla Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A 432 * registry suffix is one under which Internet users can directly register names via a domain name 433 * registrar, and have such registrations lawfully protected by internet-governing bodies such as 434 * ICANN. Examples of registry suffixes include {@code com}, {@code co.uk}, and {@code 435 * pvt.k12.wy.us}. Examples of domain names that are <i>not</i> registry suffixes include {@code 436 * google.com} and {@code foo.co.uk}. 437 * 438 * <p>Registry suffixes are a proper subset of {@linkplain #isPublicSuffix() public suffixes}. The 439 * list of public suffixes additionally contains privately owned domain names under which Internet 440 * users can register subdomains. An example of a public suffix that is not a registry suffix is 441 * {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> registry 442 * suffixes, since domain name registries collectively control all internet domain names. 443 * 444 * <p>For considerations on whether the public suffix or registry suffix designation is more 445 * suitable for your application, see <a 446 * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. 447 * 448 * @return {@code true} if this domain name appears exactly on the public suffix list as part of 449 * the registry suffix section (labelled "ICANN"). 450 * @since 23.3 451 */ 452 public boolean isRegistrySuffix() { 453 return registrySuffixIndex() == 0; 454 } 455 456 /** 457 * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, 458 * including if it is a registry suffix itself. For example, returns {@code true} for {@code 459 * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code 460 * google.invalid}. 461 * 462 * <p>Note that this method is equivalent to {@link #hasPublicSuffix()} because all registry 463 * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. 464 * 465 * @since 23.3 466 */ 467 public boolean hasRegistrySuffix() { 468 return registrySuffixIndex() != NO_SUFFIX_FOUND; 469 } 470 471 /** 472 * Returns the {@linkplain #isRegistrySuffix() registry suffix} portion of the domain name, or 473 * {@code null} if no registry suffix is present. 474 * 475 * @since 23.3 476 */ 477 public @Nullable InternetDomainName registrySuffix() { 478 return hasRegistrySuffix() ? ancestor(registrySuffixIndex()) : null; 479 } 480 481 /** 482 * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, 483 * while not being a registry suffix itself. For example, returns {@code true} for {@code 484 * www.google.com}, {@code foo.co.uk} and {@code blogspot.com}, but not for {@code com}, {@code 485 * co.uk}, or {@code google.invalid}. 486 * 487 * @since 23.3 488 */ 489 public boolean isUnderRegistrySuffix() { 490 return registrySuffixIndex() > 0; 491 } 492 493 /** 494 * Indicates whether this domain name is composed of exactly one subdomain component followed by a 495 * {@linkplain #isRegistrySuffix() registry suffix}. For example, returns {@code true} for {@code 496 * google.com}, {@code foo.co.uk}, and {@code blogspot.com}, but not for {@code www.google.com}, 497 * {@code co.uk}, or {@code myblog.blogspot.com}. 498 * 499 * <p><b>Warning:</b> This method should not be used to determine the probable highest level 500 * parent domain for which cookies may be set. Use {@link #topPrivateDomain()} for that purpose. 501 * 502 * @since 23.3 503 */ 504 public boolean isTopDomainUnderRegistrySuffix() { 505 return registrySuffixIndex() == 1; 506 } 507 508 /** 509 * Returns the portion of this domain name that is one level beneath the {@linkplain 510 * #isRegistrySuffix() registry suffix}. For example, for {@code x.adwords.google.co.uk} it 511 * returns {@code google.co.uk}, since {@code co.uk} is a registry suffix. Similarly, for {@code 512 * myblog.blogspot.com} it returns {@code blogspot.com}, since {@code com} is a registry suffix. 513 * 514 * <p>If {@link #isTopDomainUnderRegistrySuffix()} is true, the current domain name instance is 515 * returned. 516 * 517 * <p><b>Warning:</b> This method should not be used to determine whether a domain is probably the 518 * highest level for which cookies may be set. Use {@link #isTopPrivateDomain()} for that purpose. 519 * 520 * @throws IllegalStateException if this domain does not end with a registry suffix 521 * @since 23.3 522 */ 523 public InternetDomainName topDomainUnderRegistrySuffix() { 524 if (isTopDomainUnderRegistrySuffix()) { 525 return this; 526 } 527 checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); 528 return ancestor(registrySuffixIndex() - 1); 529 } 530 531 /** Indicates whether this domain is composed of two or more parts. */ 532 public boolean hasParent() { 533 return parts.size() > 1; 534 } 535 536 /** 537 * Returns an {@code InternetDomainName} that is the immediate ancestor of this one; that is, the 538 * current domain with the leftmost part removed. For example, the parent of {@code 539 * www.google.com} is {@code google.com}. 540 * 541 * @throws IllegalStateException if the domain has no parent, as determined by {@link #hasParent} 542 */ 543 public InternetDomainName parent() { 544 checkState(hasParent(), "Domain '%s' has no parent", name); 545 return ancestor(1); 546 } 547 548 /** 549 * Returns the ancestor of the current domain at the given number of levels "higher" (rightward) 550 * in the subdomain list. The number of levels must be non-negative, and less than {@code N-1}, 551 * where {@code N} is the number of parts in the domain. 552 * 553 * <p>TODO: Reasonable candidate for addition to public API. 554 */ 555 private InternetDomainName ancestor(int levels) { 556 ImmutableList<String> ancestorParts = parts.subList(levels, parts.size()); 557 558 // levels equals the number of dots that are getting clipped away, then add the length of each 559 // clipped part to get the length of the leading substring that is being removed. 560 int substringFrom = levels; 561 for (int i = 0; i < levels; i++) { 562 substringFrom += parts.get(i).length(); 563 } 564 String ancestorName = name.substring(substringFrom); 565 566 return new InternetDomainName(ancestorName, ancestorParts); 567 } 568 569 /** 570 * Creates and returns a new {@code InternetDomainName} by prepending the argument and a dot to 571 * the current name. For example, {@code InternetDomainName.from("foo.com").child("www.bar")} 572 * returns a new {@code InternetDomainName} with the value {@code www.bar.foo.com}. Only lenient 573 * validation is performed, as described {@link #from(String) here}. 574 * 575 * @throws NullPointerException if leftParts is null 576 * @throws IllegalArgumentException if the resulting name is not valid 577 */ 578 public InternetDomainName child(String leftParts) { 579 return from(checkNotNull(leftParts) + "." + name); 580 } 581 582 /** 583 * Indicates whether the argument is a syntactically valid domain name using lenient validation. 584 * Specifically, validation against <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a> 585 * ("Internationalizing Domain Names in Applications") is skipped. 586 * 587 * <p>The following two code snippets are equivalent: 588 * 589 * {@snippet : 590 * domainName = InternetDomainName.isValid(name) 591 * ? InternetDomainName.from(name) 592 * : DEFAULT_DOMAIN; 593 * } 594 * 595 * {@snippet : 596 * try { 597 * domainName = InternetDomainName.from(name); 598 * } catch (IllegalArgumentException e) { 599 * domainName = DEFAULT_DOMAIN; 600 * } 601 * } 602 * 603 * @since 8.0 (previously named {@code isValidLenient}) 604 */ 605 public static boolean isValid(String name) { 606 try { 607 InternetDomainName unused = from(name); 608 return true; 609 } catch (IllegalArgumentException e) { 610 return false; 611 } 612 } 613 614 /** Returns the domain name, normalized to all lower case. */ 615 @Override 616 public String toString() { 617 return name; 618 } 619 620 /** 621 * Equality testing is based on the text supplied by the caller, after normalization as described 622 * in the class documentation. For example, a non-ASCII Unicode domain name and the Punycode 623 * version of the same domain name would not be considered equal. 624 */ 625 @Override 626 public boolean equals(@Nullable Object object) { 627 if (object == this) { 628 return true; 629 } 630 631 if (object instanceof InternetDomainName) { 632 InternetDomainName that = (InternetDomainName) object; 633 return this.name.equals(that.name); 634 } 635 636 return false; 637 } 638 639 @Override 640 public int hashCode() { 641 return name.hashCode(); 642 } 643}