diff --git a/android/guava/src/com/google/common/net/InternetDomainName.java b/android/guava/src/com/google/common/net/InternetDomainName.java index 4f85fb67c124..ba28e674793f 100644 --- a/android/guava/src/com/google/common/net/InternetDomainName.java +++ b/android/guava/src/com/google/common/net/InternetDomainName.java @@ -81,11 +81,17 @@ public final class InternetDomainName { private static final Joiner DOT_JOINER = Joiner.on('.'); /** - * Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no + * Value of {@link #publicSuffixIndex()} or {@link #registrySuffixIndex()} which indicates that no * relevant suffix was found. */ private static final int NO_SUFFIX_FOUND = -1; + /** + * Value of {@link #publicSuffixIndexCache} or {@link #registrySuffixIndexCache} which indicates + * that they were not initialized yet. + */ + private static final int SUFFIX_NOT_INITIALIZED = -2; + /** * Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described * in RFC 2181 part 11 with the fact that the @@ -113,20 +119,24 @@ public final class InternetDomainName { private final ImmutableList parts; /** - * The index in the {@link #parts()} list at which the public suffix begins. For example, for the - * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code - * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public - * suffix was found. + * Cached value of #publicSuffixIndex(). Do not use directly. + * + *

Since this field isn't {@code volatile}, if an instance of this class is shared across + * threads before it is initialized, then each thread is likely to compute their own copy of the + * value. */ - private final int publicSuffixIndex; + @SuppressWarnings("Immutable") + private int publicSuffixIndexCache = SUFFIX_NOT_INITIALIZED; /** - * The index in the {@link #parts()} list at which the registry suffix begins. For example, for - * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code - * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix - * was found. + * Cached value of #registrySuffixIndex(). Do not use directly. + * + *

Since this field isn't {@code volatile}, if an instance of this class is shared across + * threads before it is initialized, then each thread is likely to compute their own copy of the + * value. */ - private final int registrySuffixIndex; + @SuppressWarnings("Immutable") + private int registrySuffixIndexCache = SUFFIX_NOT_INITIALIZED; /** Constructor used to implement {@link #from(String)}, and from subclasses. */ InternetDomainName(String name) { @@ -147,9 +157,32 @@ public final class InternetDomainName { this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); + } + + /** + * The index in the {@link #parts()} list at which the public suffix begins. For example, for the + * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code + * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public + * suffix was found. + */ + private int publicSuffixIndex() { + if (publicSuffixIndexCache == SUFFIX_NOT_INITIALIZED) { + publicSuffixIndexCache = findSuffixOfType(Optional.absent()); + } + return publicSuffixIndexCache; + } - this.publicSuffixIndex = findSuffixOfType(Optional.absent()); - this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); + /** + * The index in the {@link #parts()} list at which the registry suffix begins. For example, for + * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code + * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix + * was found. + */ + private int registrySuffixIndex() { + if (registrySuffixIndexCache == SUFFIX_NOT_INITIALIZED) { + registrySuffixIndexCache = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); + } + return registrySuffixIndexCache; } /** @@ -331,7 +364,7 @@ public ImmutableList parts() { * @since 6.0 */ public boolean isPublicSuffix() { - return publicSuffixIndex == 0; + return publicSuffixIndex() == 0; } /** @@ -347,7 +380,7 @@ public boolean isPublicSuffix() { * @since 6.0 */ public boolean hasPublicSuffix() { - return publicSuffixIndex != NO_SUFFIX_FOUND; + return publicSuffixIndex() != NO_SUFFIX_FOUND; } /** @@ -358,7 +391,7 @@ public boolean hasPublicSuffix() { */ @CheckForNull public InternetDomainName publicSuffix() { - return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null; + return hasPublicSuffix() ? ancestor(publicSuffixIndex()) : null; } /** @@ -374,7 +407,7 @@ public InternetDomainName publicSuffix() { * @since 6.0 */ public boolean isUnderPublicSuffix() { - return publicSuffixIndex > 0; + return publicSuffixIndex() > 0; } /** @@ -390,7 +423,7 @@ public boolean isUnderPublicSuffix() { * @since 6.0 */ public boolean isTopPrivateDomain() { - return publicSuffixIndex == 1; + return publicSuffixIndex() == 1; } /** @@ -414,7 +447,7 @@ public InternetDomainName topPrivateDomain() { return this; } checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); - return ancestor(publicSuffixIndex - 1); + return ancestor(publicSuffixIndex() - 1); } /** @@ -441,7 +474,7 @@ public InternetDomainName topPrivateDomain() { * @since 23.3 */ public boolean isRegistrySuffix() { - return registrySuffixIndex == 0; + return registrySuffixIndex() == 0; } /** @@ -456,7 +489,7 @@ public boolean isRegistrySuffix() { * @since 23.3 */ public boolean hasRegistrySuffix() { - return registrySuffixIndex != NO_SUFFIX_FOUND; + return registrySuffixIndex() != NO_SUFFIX_FOUND; } /** @@ -467,7 +500,7 @@ public boolean hasRegistrySuffix() { */ @CheckForNull public InternetDomainName registrySuffix() { - return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null; + return hasRegistrySuffix() ? ancestor(registrySuffixIndex()) : null; } /** @@ -479,7 +512,7 @@ public InternetDomainName registrySuffix() { * @since 23.3 */ public boolean isUnderRegistrySuffix() { - return registrySuffixIndex > 0; + return registrySuffixIndex() > 0; } /** @@ -494,7 +527,7 @@ public boolean isUnderRegistrySuffix() { * @since 23.3 */ public boolean isTopDomainUnderRegistrySuffix() { - return registrySuffixIndex == 1; + return registrySuffixIndex() == 1; } /** @@ -517,7 +550,7 @@ public InternetDomainName topDomainUnderRegistrySuffix() { return this; } checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); - return ancestor(registrySuffixIndex - 1); + return ancestor(registrySuffixIndex() - 1); } /** Indicates whether this domain is composed of two or more parts. */ diff --git a/guava/src/com/google/common/net/InternetDomainName.java b/guava/src/com/google/common/net/InternetDomainName.java index 4f85fb67c124..ba28e674793f 100644 --- a/guava/src/com/google/common/net/InternetDomainName.java +++ b/guava/src/com/google/common/net/InternetDomainName.java @@ -81,11 +81,17 @@ public final class InternetDomainName { private static final Joiner DOT_JOINER = Joiner.on('.'); /** - * Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no + * Value of {@link #publicSuffixIndex()} or {@link #registrySuffixIndex()} which indicates that no * relevant suffix was found. */ private static final int NO_SUFFIX_FOUND = -1; + /** + * Value of {@link #publicSuffixIndexCache} or {@link #registrySuffixIndexCache} which indicates + * that they were not initialized yet. + */ + private static final int SUFFIX_NOT_INITIALIZED = -2; + /** * Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described * in RFC 2181 part 11 with the fact that the @@ -113,20 +119,24 @@ public final class InternetDomainName { private final ImmutableList parts; /** - * The index in the {@link #parts()} list at which the public suffix begins. For example, for the - * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code - * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public - * suffix was found. + * Cached value of #publicSuffixIndex(). Do not use directly. + * + *

Since this field isn't {@code volatile}, if an instance of this class is shared across + * threads before it is initialized, then each thread is likely to compute their own copy of the + * value. */ - private final int publicSuffixIndex; + @SuppressWarnings("Immutable") + private int publicSuffixIndexCache = SUFFIX_NOT_INITIALIZED; /** - * The index in the {@link #parts()} list at which the registry suffix begins. For example, for - * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code - * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix - * was found. + * Cached value of #registrySuffixIndex(). Do not use directly. + * + *

Since this field isn't {@code volatile}, if an instance of this class is shared across + * threads before it is initialized, then each thread is likely to compute their own copy of the + * value. */ - private final int registrySuffixIndex; + @SuppressWarnings("Immutable") + private int registrySuffixIndexCache = SUFFIX_NOT_INITIALIZED; /** Constructor used to implement {@link #from(String)}, and from subclasses. */ InternetDomainName(String name) { @@ -147,9 +157,32 @@ public final class InternetDomainName { this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name); checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name); + } + + /** + * The index in the {@link #parts()} list at which the public suffix begins. For example, for the + * domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code + * blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public + * suffix was found. + */ + private int publicSuffixIndex() { + if (publicSuffixIndexCache == SUFFIX_NOT_INITIALIZED) { + publicSuffixIndexCache = findSuffixOfType(Optional.absent()); + } + return publicSuffixIndexCache; + } - this.publicSuffixIndex = findSuffixOfType(Optional.absent()); - this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); + /** + * The index in the {@link #parts()} list at which the registry suffix begins. For example, for + * the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code + * co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix + * was found. + */ + private int registrySuffixIndex() { + if (registrySuffixIndexCache == SUFFIX_NOT_INITIALIZED) { + registrySuffixIndexCache = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY)); + } + return registrySuffixIndexCache; } /** @@ -331,7 +364,7 @@ public ImmutableList parts() { * @since 6.0 */ public boolean isPublicSuffix() { - return publicSuffixIndex == 0; + return publicSuffixIndex() == 0; } /** @@ -347,7 +380,7 @@ public boolean isPublicSuffix() { * @since 6.0 */ public boolean hasPublicSuffix() { - return publicSuffixIndex != NO_SUFFIX_FOUND; + return publicSuffixIndex() != NO_SUFFIX_FOUND; } /** @@ -358,7 +391,7 @@ public boolean hasPublicSuffix() { */ @CheckForNull public InternetDomainName publicSuffix() { - return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null; + return hasPublicSuffix() ? ancestor(publicSuffixIndex()) : null; } /** @@ -374,7 +407,7 @@ public InternetDomainName publicSuffix() { * @since 6.0 */ public boolean isUnderPublicSuffix() { - return publicSuffixIndex > 0; + return publicSuffixIndex() > 0; } /** @@ -390,7 +423,7 @@ public boolean isUnderPublicSuffix() { * @since 6.0 */ public boolean isTopPrivateDomain() { - return publicSuffixIndex == 1; + return publicSuffixIndex() == 1; } /** @@ -414,7 +447,7 @@ public InternetDomainName topPrivateDomain() { return this; } checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name); - return ancestor(publicSuffixIndex - 1); + return ancestor(publicSuffixIndex() - 1); } /** @@ -441,7 +474,7 @@ public InternetDomainName topPrivateDomain() { * @since 23.3 */ public boolean isRegistrySuffix() { - return registrySuffixIndex == 0; + return registrySuffixIndex() == 0; } /** @@ -456,7 +489,7 @@ public boolean isRegistrySuffix() { * @since 23.3 */ public boolean hasRegistrySuffix() { - return registrySuffixIndex != NO_SUFFIX_FOUND; + return registrySuffixIndex() != NO_SUFFIX_FOUND; } /** @@ -467,7 +500,7 @@ public boolean hasRegistrySuffix() { */ @CheckForNull public InternetDomainName registrySuffix() { - return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null; + return hasRegistrySuffix() ? ancestor(registrySuffixIndex()) : null; } /** @@ -479,7 +512,7 @@ public InternetDomainName registrySuffix() { * @since 23.3 */ public boolean isUnderRegistrySuffix() { - return registrySuffixIndex > 0; + return registrySuffixIndex() > 0; } /** @@ -494,7 +527,7 @@ public boolean isUnderRegistrySuffix() { * @since 23.3 */ public boolean isTopDomainUnderRegistrySuffix() { - return registrySuffixIndex == 1; + return registrySuffixIndex() == 1; } /** @@ -517,7 +550,7 @@ public InternetDomainName topDomainUnderRegistrySuffix() { return this; } checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name); - return ancestor(registrySuffixIndex - 1); + return ancestor(registrySuffixIndex() - 1); } /** Indicates whether this domain is composed of two or more parts. */