Coverage Summary for Class: InternetDomainName (com.google.common.net)

Class Class, % Method, % Line, %
InternetDomainName 0% (0/1) 0% (0/29) 0% (0/91)


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