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