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.Beta; 022import com.google.common.annotations.GwtCompatible; 023import com.google.common.base.Ascii; 024import com.google.common.base.CharMatcher; 025import com.google.common.base.Joiner; 026import com.google.common.base.Optional; 027import com.google.common.base.Splitter; 028import com.google.common.collect.ImmutableList; 029import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; 030import com.google.thirdparty.publicsuffix.PublicSuffixType; 031import java.util.List; 032import javax.annotation.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@Beta 074@GwtCompatible 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 private static final Joiner DOT_JOINER = Joiner.on('.'); 080 081 /** 082 * Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no 083 * relevant suffix was found. 084 */ 085 private static final int NO_SUFFIX_FOUND = -1; 086 087 private static final String DOT_REGEX = "\\."; 088 089 /** 090 * Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described 091 * in <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11 with the fact that the 092 * encoding of each part occupies at least two bytes (dot plus label externally, length byte plus 093 * label internally). Thus, if all labels have the minimum size of one byte, 127 of them will fit. 094 */ 095 private static final int MAX_PARTS = 127; 096 097 /** 098 * Maximum length of a full domain name, including separators, and leaving room for the root 099 * label. See <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11. 100 */ 101 private static final int MAX_LENGTH = 253; 102 103 /** 104 * Maximum size of a single part of a domain name. See 105 * <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11. 106 */ 107 private static final int MAX_DOMAIN_PART_LENGTH = 63; 108 109 /** 110 * The full domain name, converted to lower case. 111 */ 112 private final String name; 113 114 /** 115 * The parts of the domain name, converted to lower case. 116 */ 117 private final ImmutableList<String> parts; 118 119 /** 120 * The index in the {@link #parts()} list at which the public suffix begins. For example, for the 121 * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code 122 * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public 123 * suffix was found. 124 */ 125 private final int publicSuffixIndex; 126 127 /** 128 * The index in the {@link #parts()} list at which the registry suffix begins. For example, for 129 * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code 130 * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix 131 * was found. 132 */ 133 private final int registrySuffixIndex; 134 135 /** 136 * Constructor used to implement {@link #from(String)}, and from subclasses. 137 */ 138 InternetDomainName(String name) { 139 // Normalize: 140 // * ASCII characters to lowercase 141 // * All dot-like characters to '.' 142 // * Strip trailing '.' 143 144 name = Ascii.toLowerCase(DOTS_MATCHER.replaceFrom(name, '.')); 145 146 if (name.endsWith(".")) { 147 name = name.substring(0, name.length() - 1); 148 } 149 150 checkArgument(name.length() <= MAX_LENGTH, "Domain name too long: '%s':", name); 151 this.name = name; 152 153 this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); 154 checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); 155 checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); 156 157 this.publicSuffixIndex = findSuffixOfType(Optional.<PublicSuffixType>absent()); 158 this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); 159 } 160 161 /** 162 * Returns the index of the leftmost part of the suffix, or -1 if not found. Note that the value 163 * defined as a suffix may not produce {@code true} results from {@link #isPublicSuffix()} or 164 * {@link #isRegistrySuffix()} if the domain ends with an excluded domain pattern such as {@code 165 * "nhs.uk"}. 166 * 167 * <p>If a {@code desiredType} is specified, this method only finds suffixes of the given type. 168 * Otherwise, it finds the first suffix of any type. 169 */ 170 private int findSuffixOfType(Optional<PublicSuffixType> desiredType) { 171 final int partsSize = parts.size(); 172 173 for (int i = 0; i < partsSize; i++) { 174 String ancestorName = DOT_JOINER.join(parts.subList(i, partsSize)); 175 176 if (matchesType( 177 desiredType, Optional.fromNullable(PublicSuffixPatterns.EXACT.get(ancestorName)))) { 178 return i; 179 } 180 181 // Excluded domains (e.g. !nhs.uk) use the next highest 182 // domain as the effective public suffix (e.g. uk). 183 184 if (PublicSuffixPatterns.EXCLUDED.containsKey(ancestorName)) { 185 return i + 1; 186 } 187 188 if (matchesWildcardSuffixType(desiredType, ancestorName)) { 189 return i; 190 } 191 } 192 193 return NO_SUFFIX_FOUND; 194 } 195 196 /** 197 * Returns an instance of {@link InternetDomainName} after lenient validation. Specifically, 198 * validation against <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a> 199 * ("Internationalizing Domain Names in Applications") is skipped, while validation against <a 200 * href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> is relaxed in the following ways: 201 * 202 * <ul> 203 * <li>Any part containing non-ASCII characters is considered valid. 204 * <li>Underscores ('_') are permitted wherever dashes ('-') are permitted. 205 * <li>Parts other than the final part may start with a digit, as mandated by <a 206 * href="https://tools.ietf.org/html/rfc1123#section-2">RFC 1123</a>. 207 * </ul> 208 * 209 * 210 * @param domain A domain name (not IP address) 211 * @throws IllegalArgumentException if {@code name} is not syntactically valid according to {@link 212 * #isValid} 213 * @since 10.0 (previously named {@code fromLenient}) 214 */ 215 public static InternetDomainName from(String domain) { 216 return new InternetDomainName(checkNotNull(domain)); 217 } 218 219 /** 220 * Validation method used by {@code from} to ensure that the domain name is syntactically valid 221 * according to RFC 1035. 222 * 223 * @return Is the domain name syntactically valid? 224 */ 225 private static boolean validateSyntax(List<String> parts) { 226 final int lastIndex = parts.size() - 1; 227 228 // Validate the last part specially, as it has different syntax rules. 229 230 if (!validatePart(parts.get(lastIndex), true)) { 231 return false; 232 } 233 234 for (int i = 0; i < lastIndex; i++) { 235 String part = parts.get(i); 236 if (!validatePart(part, false)) { 237 return false; 238 } 239 } 240 241 return true; 242 } 243 244 private static final CharMatcher DASH_MATCHER = CharMatcher.anyOf("-_"); 245 246 private static final CharMatcher PART_CHAR_MATCHER = 247 CharMatcher.javaLetterOrDigit().or(DASH_MATCHER); 248 249 /** 250 * Helper method for {@link #validateSyntax(List)}. Validates that one part of a domain name is 251 * valid. 252 * 253 * @param part The domain name part to be validated 254 * @param isFinalPart Is this the final (rightmost) domain part? 255 * @return Whether the part is valid 256 */ 257 private static boolean validatePart(String part, boolean isFinalPart) { 258 259 // These tests could be collapsed into one big boolean expression, but 260 // they have been left as independent tests for clarity. 261 262 if (part.length() < 1 || part.length() > MAX_DOMAIN_PART_LENGTH) { 263 return false; 264 } 265 266 /* 267 * GWT claims to support java.lang.Character's char-classification methods, but it actually only 268 * works for ASCII. So for now, assume any non-ASCII characters are valid. The only place this 269 * seems to be documented is here: 270 * http://osdir.com/ml/GoogleWebToolkitContributors/2010-03/msg00178.html 271 * 272 * <p>ASCII characters in the part are expected to be valid per RFC 1035, with underscore also 273 * being allowed due to widespread practice. 274 */ 275 276 String asciiChars = CharMatcher.ascii().retainFrom(part); 277 278 if (!PART_CHAR_MATCHER.matchesAllOf(asciiChars)) { 279 return false; 280 } 281 282 // No initial or final dashes or underscores. 283 284 if (DASH_MATCHER.matches(part.charAt(0)) 285 || DASH_MATCHER.matches(part.charAt(part.length() - 1))) { 286 return false; 287 } 288 289 /* 290 * Note that we allow (in contravention of a strict interpretation of the relevant RFCs) domain 291 * parts other than the last may begin with a digit (for example, "3com.com"). It's important to 292 * disallow an initial digit in the last part; it's the only thing that stops an IPv4 numeric 293 * address like 127.0.0.1 from looking like a valid domain name. 294 */ 295 296 if (isFinalPart && CharMatcher.digit().matches(part.charAt(0))) { 297 return false; 298 } 299 300 return true; 301 } 302 303 /** 304 * Returns the individual components of this domain name, normalized to all lower case. For 305 * example, for the domain name {@code mail.google.com}, this method returns the list 306 * {@code ["mail", "google", "com"]}. 307 */ 308 public ImmutableList<String> parts() { 309 return parts; 310 } 311 312 /** 313 * Indicates whether this domain name represents a <i>public suffix</i>, as defined by the Mozilla 314 * Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A public suffix 315 * is one under which Internet users can directly register names, such as {@code com}, {@code 316 * co.uk} or {@code pvt.k12.wy.us}. Examples of domain names that are <i>not</i> public suffixes 317 * include {@code google.com}, {@code foo.co.uk}, and {@code myblog.blogspot.com}. 318 * 319 * <p>Public suffixes are a proper superset of {@linkplain #isRegistrySuffix() registry suffixes}. 320 * The list of public suffixes additionally contains privately owned domain names under which 321 * Internet users can register subdomains. An example of a public suffix that is not a registry 322 * suffix is {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> 323 * registry suffixes, since domain name registries collectively control all internet domain names. 324 * 325 * <p>For considerations on whether the public suffix or registry suffix designation is more 326 * suitable for your application, see <a 327 * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. 328 * 329 * @return {@code true} if this domain name appears exactly on the public suffix list 330 * @since 6.0 331 */ 332 public boolean isPublicSuffix() { 333 return publicSuffixIndex == 0; 334 } 335 336 /** 337 * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, 338 * including if it is a public suffix itself. For example, returns {@code true} for {@code 339 * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code 340 * google.invalid}. This is the recommended method for determining whether a domain is potentially 341 * an addressable host. 342 * 343 * <p>Note that this method is equivalent to {@link #hasRegistrySuffix()} because all registry 344 * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. 345 * 346 * @since 6.0 347 */ 348 public boolean hasPublicSuffix() { 349 return publicSuffixIndex != NO_SUFFIX_FOUND; 350 } 351 352 /** 353 * Returns the {@linkplain #isPublicSuffix() public suffix} portion of the domain name, or 354 * {@code null} if no public suffix is present. 355 * 356 * @since 6.0 357 */ 358 public InternetDomainName publicSuffix() { 359 return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null; 360 } 361 362 /** 363 * Indicates whether this domain name ends in a {@linkplain #isPublicSuffix() public suffix}, 364 * while not being a public suffix itself. For example, returns {@code true} for {@code 365 * www.google.com}, {@code foo.co.uk} and {@code myblog.blogspot.com}, but not for {@code com}, 366 * {@code co.uk}, {@code google.invalid}, or {@code blogspot.com}. 367 * 368 * <p>This method can be used to determine whether it will probably be possible to set cookies on 369 * the domain, though even that depends on individual browsers' implementations of cookie 370 * controls. See <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> for details. 371 * 372 * @since 6.0 373 */ 374 public boolean isUnderPublicSuffix() { 375 return publicSuffixIndex > 0; 376 } 377 378 /** 379 * Indicates whether this domain name is composed of exactly one subdomain component followed by a 380 * {@linkplain #isPublicSuffix() public suffix}. For example, returns {@code true} for {@code 381 * google.com} {@code foo.co.uk}, and {@code myblog.blogspot.com}, but not for {@code 382 * www.google.com}, {@code co.uk}, or {@code blogspot.com}. 383 * 384 * <p>This method can be used to determine whether a domain is probably the highest level for 385 * which cookies may be set, though even that depends on individual browsers' implementations of 386 * cookie controls. See <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> for details. 387 * 388 * @since 6.0 389 */ 390 public boolean isTopPrivateDomain() { 391 return publicSuffixIndex == 1; 392 } 393 394 /** 395 * Returns the portion of this domain name that is one level beneath the {@linkplain 396 * #isPublicSuffix() public suffix}. For example, for {@code x.adwords.google.co.uk} it returns 397 * {@code google.co.uk}, since {@code co.uk} is a public suffix. Similarly, for {@code 398 * myblog.blogspot.com} it returns the same domain, {@code myblog.blogspot.com}, since {@code 399 * blogspot.com} is a public suffix. 400 * 401 * <p>If {@link #isTopPrivateDomain()} is true, the current domain name instance is returned. 402 * 403 * <p>This method can be used to determine the probable highest level parent domain for which 404 * cookies may be set, though even that depends on individual browsers' implementations of cookie 405 * controls. 406 * 407 * @throws IllegalStateException if this domain does not end with a public suffix 408 * @since 6.0 409 */ 410 public InternetDomainName topPrivateDomain() { 411 if (isTopPrivateDomain()) { 412 return this; 413 } 414 checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); 415 return ancestor(publicSuffixIndex - 1); 416 } 417 418 /** 419 * Indicates whether this domain name represents a <i>registry suffix</i>, as defined by a subset 420 * of the Mozilla Foundation's <a href="http://publicsuffix.org/">Public Suffix List</a> (PSL). A 421 * registry suffix is one under which Internet users can directly register names via a domain name 422 * registrar, and have such registrations lawfully protected by internet-governing bodies such as 423 * ICANN. Examples of registry suffixes include {@code com}, {@code co.uk}, and {@code 424 * pvt.k12.wy.us}. Examples of domain names that are <i>not</i> registry suffixes include {@code 425 * google.com} and {@code foo.co.uk}. 426 * 427 * <p>Registry suffixes are a proper subset of {@linkplain #isPublicSuffix() public suffixes}. The 428 * list of public suffixes additionally contains privately owned domain names under which Internet 429 * users can register subdomains. An example of a public suffix that is not a registry suffix is 430 * {@code blogspot.com}. Note that it is true that all public suffixes <i>have</i> registry 431 * suffixes, since domain name registries collectively control all internet domain names. 432 * 433 * <p>For considerations on whether the public suffix or registry suffix designation is more 434 * suitable for your application, see <a 435 * href="https://github.com/google/guava/wiki/InternetDomainNameExplained">this article</a>. 436 * 437 * @return {@code true} if this domain name appears exactly on the public suffix list as part of 438 * the registry suffix section (labelled "ICANN"). 439 * @since 23.3 440 */ 441 public boolean isRegistrySuffix() { 442 return registrySuffixIndex == 0; 443 } 444 445 /** 446 * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, 447 * including if it is a registry suffix itself. For example, returns {@code true} for {@code 448 * www.google.com}, {@code foo.co.uk} and {@code com}, but not for {@code invalid} or {@code 449 * google.invalid}. 450 * 451 * <p>Note that this method is equivalent to {@link #hasPublicSuffix()} because all registry 452 * suffixes are public suffixes <i>and</i> all public suffixes have registry suffixes. 453 * 454 * @since 23.3 455 */ 456 public boolean hasRegistrySuffix() { 457 return registrySuffixIndex != NO_SUFFIX_FOUND; 458 } 459 460 /** 461 * Returns the {@linkplain #isRegistrySuffix() registry suffix} portion of the domain name, or 462 * {@code null} if no registry suffix is present. 463 * 464 * @since 23.3 465 */ 466 public InternetDomainName registrySuffix() { 467 return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null; 468 } 469 470 /** 471 * Indicates whether this domain name ends in a {@linkplain #isRegistrySuffix() registry suffix}, 472 * while not being a registry suffix itself. For example, returns {@code true} for {@code 473 * www.google.com}, {@code foo.co.uk} and {@code blogspot.com}, but not for {@code com}, {@code 474 * co.uk}, or {@code google.invalid}. 475 * 476 * @since 23.3 477 */ 478 public boolean isUnderRegistrySuffix() { 479 return registrySuffixIndex > 0; 480 } 481 482 /** 483 * Indicates whether this domain name is composed of exactly one subdomain component followed by a 484 * {@linkplain #isRegistrySuffix() registry suffix}. For example, returns {@code true} for {@code 485 * google.com}, {@code foo.co.uk}, and {@code blogspot.com}, but not for {@code www.google.com}, 486 * {@code co.uk}, or {@code myblog.blogspot.com}. 487 * 488 * <p><b>Warning:</b> This method should not be used to determine the probable highest level 489 * parent domain for which cookies may be set. Use {@link #topPrivateDomain()} for that purpose. 490 * 491 * @since 23.3 492 */ 493 public boolean isTopDomainUnderRegistrySuffix() { 494 return registrySuffixIndex == 1; 495 } 496 497 /** 498 * Returns the portion of this domain name that is one level beneath the {@linkplain 499 * #isRegistrySuffix() registry suffix}. For example, for {@code x.adwords.google.co.uk} it 500 * returns {@code google.co.uk}, since {@code co.uk} is a registry suffix. Similarly, for {@code 501 * myblog.blogspot.com} it returns {@code blogspot.com}, since {@code com} is a registry suffix. 502 * 503 * <p>If {@link #isTopDomainUnderRegistrySuffix()} is true, the current domain name instance is 504 * returned. 505 * 506 * <p><b>Warning:</b> This method should not be used to determine whether a domain is probably the 507 * highest level for which cookies may be set. Use {@link #isTopPrivateDomain()} for that purpose. 508 * 509 * @throws IllegalStateException if this domain does not end with a registry suffix 510 * @since 23.3 511 */ 512 public InternetDomainName topDomainUnderRegistrySuffix() { 513 if (isTopDomainUnderRegistrySuffix()) { 514 return this; 515 } 516 checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); 517 return ancestor(registrySuffixIndex - 1); 518 } 519 520 /** 521 * Indicates whether this domain is composed of two or more parts. 522 */ 523 public boolean hasParent() { 524 return parts.size() > 1; 525 } 526 527 /** 528 * Returns an {@code InternetDomainName} that is the immediate ancestor of this one; that is, the 529 * current domain with the leftmost part removed. For example, the parent of 530 * {@code www.google.com} is {@code google.com}. 531 * 532 * @throws IllegalStateException if the domain has no parent, as determined by {@link #hasParent} 533 */ 534 public InternetDomainName parent() { 535 checkState(hasParent(), "Domain '%s' has no parent", name); 536 return ancestor(1); 537 } 538 539 /** 540 * Returns the ancestor of the current domain at the given number of levels "higher" (rightward) 541 * in the subdomain list. The number of levels must be non-negative, and less than {@code N-1}, 542 * where {@code N} is the number of parts in the domain. 543 * 544 * <p>TODO: Reasonable candidate for addition to public API. 545 */ 546 private InternetDomainName ancestor(int levels) { 547 return from(DOT_JOINER.join(parts.subList(levels, parts.size()))); 548 } 549 550 /** 551 * Creates and returns a new {@code InternetDomainName} by prepending the argument and a dot to 552 * the current name. For example, {@code 553 * InternetDomainName.from("foo.com").child("www.bar")} returns a new {@code InternetDomainName} 554 * with the value {@code www.bar.foo.com}. Only lenient validation is performed, as described 555 * {@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;}</pre> 575 * 576 * <pre> {@code 577 * try { 578 * domainName = InternetDomainName.from(name); 579 * } catch (IllegalArgumentException e) { 580 * domainName = DEFAULT_DOMAIN; 581 * }}</pre> 582 * 583 * @since 8.0 (previously named {@code isValidLenient}) 584 */ 585 public static boolean isValid(String name) { 586 try { 587 from(name); 588 return true; 589 } catch (IllegalArgumentException e) { 590 return false; 591 } 592 } 593 594 /** 595 * Does the domain name match one of the "wildcard" patterns (e.g. {@code "*.ar"})? If a {@code 596 * desiredType} is specified, the wildcard pattern must also match that type. 597 */ 598 private static boolean matchesWildcardSuffixType( 599 Optional<PublicSuffixType> desiredType, String domain) { 600 final String[] pieces = domain.split(DOT_REGEX, 2); 601 return pieces.length == 2 602 && matchesType( 603 desiredType, Optional.fromNullable(PublicSuffixPatterns.UNDER.get(pieces[1]))); 604 } 605 606 /** 607 * If a {@code desiredType} is specified, returns true only if the {@code actualType} is 608 * identical. Otherwise, returns true as long as {@code actualType} is present. 609 */ 610 private static boolean matchesType( 611 Optional<PublicSuffixType> desiredType, Optional<PublicSuffixType> actualType) { 612 return desiredType.isPresent() ? desiredType.equals(actualType) : actualType.isPresent(); 613 } 614 615 /** 616 * Returns the domain name, normalized to all lower case. 617 */ 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 */ 629 @Override 630 public boolean equals(@Nullable Object object) { 631 if (object == this) { 632 return true; 633 } 634 635 if (object instanceof InternetDomainName) { 636 InternetDomainName that = (InternetDomainName) object; 637 return this.name.equals(that.name); 638 } 639 640 return false; 641 } 642 643 @Override 644 public int hashCode() { 645 return name.hashCode(); 646 } 647}