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}