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