Skip to content

Commit eaa62eb

Browse files
java-team-github-botGoogle Java Core Libraries
authored and
Google Java Core Libraries
committedJul 27, 2023
Lazily initialize PSL-based information in InternetDomainName.
The class does more (e.g. validation and working with parts), and not all clients are interested in PSL. RELNOTES=n/a PiperOrigin-RevId: 551612784
1 parent 3a1d18f commit eaa62eb

File tree

2 files changed

+116
-50
lines changed

2 files changed

+116
-50
lines changed
 

‎android/guava/src/com/google/common/net/InternetDomainName.java

+58-25
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,17 @@ public final class InternetDomainName {
8181
private static final Joiner DOT_JOINER = Joiner.on('.');
8282

8383
/**
84-
* Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no
84+
* Value of {@link #publicSuffixIndex()} or {@link #registrySuffixIndex()} which indicates that no
8585
* relevant suffix was found.
8686
*/
8787
private static final int NO_SUFFIX_FOUND = -1;
8888

89+
/**
90+
* Value of {@link #publicSuffixIndexCache} or {@link #registrySuffixIndexCache} which indicates
91+
* that they were not initialized yet.
92+
*/
93+
private static final int SUFFIX_NOT_INITIALIZED = -2;
94+
8995
/**
9096
* Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described
9197
* in <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11 with the fact that the
@@ -113,20 +119,24 @@ public final class InternetDomainName {
113119
private final ImmutableList<String> parts;
114120

115121
/**
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.
122+
* Cached value of #publicSuffixIndex(). Do not use directly.
123+
*
124+
* <p>Since this field isn't {@code volatile}, if an instance of this class is shared across
125+
* threads before it is initialized, then each thread is likely to compute their own copy of the
126+
* value.
120127
*/
121-
private final int publicSuffixIndex;
128+
@SuppressWarnings("Immutable")
129+
private int publicSuffixIndexCache = SUFFIX_NOT_INITIALIZED;
122130

123131
/**
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.
132+
* Cached value of #registrySuffixIndex(). Do not use directly.
133+
*
134+
* <p>Since this field isn't {@code volatile}, if an instance of this class is shared across
135+
* threads before it is initialized, then each thread is likely to compute their own copy of the
136+
* value.
128137
*/
129-
private final int registrySuffixIndex;
138+
@SuppressWarnings("Immutable")
139+
private int registrySuffixIndexCache = SUFFIX_NOT_INITIALIZED;
130140

131141
/** Constructor used to implement {@link #from(String)}, and from subclasses. */
132142
InternetDomainName(String name) {
@@ -147,9 +157,32 @@ public final class InternetDomainName {
147157
this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name));
148158
checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name);
149159
checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name);
160+
}
161+
162+
/**
163+
* The index in the {@link #parts()} list at which the public suffix begins. For example, for the
164+
* domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code
165+
* blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public
166+
* suffix was found.
167+
*/
168+
private int publicSuffixIndex() {
169+
if (publicSuffixIndexCache == SUFFIX_NOT_INITIALIZED) {
170+
publicSuffixIndexCache = findSuffixOfType(Optional.<PublicSuffixType>absent());
171+
}
172+
return publicSuffixIndexCache;
173+
}
150174

151-
this.publicSuffixIndex = findSuffixOfType(Optional.<PublicSuffixType>absent());
152-
this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY));
175+
/**
176+
* The index in the {@link #parts()} list at which the registry suffix begins. For example, for
177+
* the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code
178+
* co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix
179+
* was found.
180+
*/
181+
private int registrySuffixIndex() {
182+
if (registrySuffixIndexCache == SUFFIX_NOT_INITIALIZED) {
183+
registrySuffixIndexCache = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY));
184+
}
185+
return registrySuffixIndexCache;
153186
}
154187

155188
/**
@@ -331,7 +364,7 @@ public ImmutableList<String> parts() {
331364
* @since 6.0
332365
*/
333366
public boolean isPublicSuffix() {
334-
return publicSuffixIndex == 0;
367+
return publicSuffixIndex() == 0;
335368
}
336369

337370
/**
@@ -347,7 +380,7 @@ public boolean isPublicSuffix() {
347380
* @since 6.0
348381
*/
349382
public boolean hasPublicSuffix() {
350-
return publicSuffixIndex != NO_SUFFIX_FOUND;
383+
return publicSuffixIndex() != NO_SUFFIX_FOUND;
351384
}
352385

353386
/**
@@ -358,7 +391,7 @@ public boolean hasPublicSuffix() {
358391
*/
359392
@CheckForNull
360393
public InternetDomainName publicSuffix() {
361-
return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null;
394+
return hasPublicSuffix() ? ancestor(publicSuffixIndex()) : null;
362395
}
363396

364397
/**
@@ -374,7 +407,7 @@ public InternetDomainName publicSuffix() {
374407
* @since 6.0
375408
*/
376409
public boolean isUnderPublicSuffix() {
377-
return publicSuffixIndex > 0;
410+
return publicSuffixIndex() > 0;
378411
}
379412

380413
/**
@@ -390,7 +423,7 @@ public boolean isUnderPublicSuffix() {
390423
* @since 6.0
391424
*/
392425
public boolean isTopPrivateDomain() {
393-
return publicSuffixIndex == 1;
426+
return publicSuffixIndex() == 1;
394427
}
395428

396429
/**
@@ -414,7 +447,7 @@ public InternetDomainName topPrivateDomain() {
414447
return this;
415448
}
416449
checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name);
417-
return ancestor(publicSuffixIndex - 1);
450+
return ancestor(publicSuffixIndex() - 1);
418451
}
419452

420453
/**
@@ -441,7 +474,7 @@ public InternetDomainName topPrivateDomain() {
441474
* @since 23.3
442475
*/
443476
public boolean isRegistrySuffix() {
444-
return registrySuffixIndex == 0;
477+
return registrySuffixIndex() == 0;
445478
}
446479

447480
/**
@@ -456,7 +489,7 @@ public boolean isRegistrySuffix() {
456489
* @since 23.3
457490
*/
458491
public boolean hasRegistrySuffix() {
459-
return registrySuffixIndex != NO_SUFFIX_FOUND;
492+
return registrySuffixIndex() != NO_SUFFIX_FOUND;
460493
}
461494

462495
/**
@@ -467,7 +500,7 @@ public boolean hasRegistrySuffix() {
467500
*/
468501
@CheckForNull
469502
public InternetDomainName registrySuffix() {
470-
return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null;
503+
return hasRegistrySuffix() ? ancestor(registrySuffixIndex()) : null;
471504
}
472505

473506
/**
@@ -479,7 +512,7 @@ public InternetDomainName registrySuffix() {
479512
* @since 23.3
480513
*/
481514
public boolean isUnderRegistrySuffix() {
482-
return registrySuffixIndex > 0;
515+
return registrySuffixIndex() > 0;
483516
}
484517

485518
/**
@@ -494,7 +527,7 @@ public boolean isUnderRegistrySuffix() {
494527
* @since 23.3
495528
*/
496529
public boolean isTopDomainUnderRegistrySuffix() {
497-
return registrySuffixIndex == 1;
530+
return registrySuffixIndex() == 1;
498531
}
499532

500533
/**
@@ -517,7 +550,7 @@ public InternetDomainName topDomainUnderRegistrySuffix() {
517550
return this;
518551
}
519552
checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name);
520-
return ancestor(registrySuffixIndex - 1);
553+
return ancestor(registrySuffixIndex() - 1);
521554
}
522555

523556
/** Indicates whether this domain is composed of two or more parts. */

‎guava/src/com/google/common/net/InternetDomainName.java

+58-25
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,17 @@ public final class InternetDomainName {
8181
private static final Joiner DOT_JOINER = Joiner.on('.');
8282

8383
/**
84-
* Value of {@link #publicSuffixIndex} or {@link #registrySuffixIndex} which indicates that no
84+
* Value of {@link #publicSuffixIndex()} or {@link #registrySuffixIndex()} which indicates that no
8585
* relevant suffix was found.
8686
*/
8787
private static final int NO_SUFFIX_FOUND = -1;
8888

89+
/**
90+
* Value of {@link #publicSuffixIndexCache} or {@link #registrySuffixIndexCache} which indicates
91+
* that they were not initialized yet.
92+
*/
93+
private static final int SUFFIX_NOT_INITIALIZED = -2;
94+
8995
/**
9096
* Maximum parts (labels) in a domain name. This value arises from the 255-octet limit described
9197
* in <a href="http://www.ietf.org/rfc/rfc2181.txt">RFC 2181</a> part 11 with the fact that the
@@ -113,20 +119,24 @@ public final class InternetDomainName {
113119
private final ImmutableList<String> parts;
114120

115121
/**
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.
122+
* Cached value of #publicSuffixIndex(). Do not use directly.
123+
*
124+
* <p>Since this field isn't {@code volatile}, if an instance of this class is shared across
125+
* threads before it is initialized, then each thread is likely to compute their own copy of the
126+
* value.
120127
*/
121-
private final int publicSuffixIndex;
128+
@SuppressWarnings("Immutable")
129+
private int publicSuffixIndexCache = SUFFIX_NOT_INITIALIZED;
122130

123131
/**
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.
132+
* Cached value of #registrySuffixIndex(). Do not use directly.
133+
*
134+
* <p>Since this field isn't {@code volatile}, if an instance of this class is shared across
135+
* threads before it is initialized, then each thread is likely to compute their own copy of the
136+
* value.
128137
*/
129-
private final int registrySuffixIndex;
138+
@SuppressWarnings("Immutable")
139+
private int registrySuffixIndexCache = SUFFIX_NOT_INITIALIZED;
130140

131141
/** Constructor used to implement {@link #from(String)}, and from subclasses. */
132142
InternetDomainName(String name) {
@@ -147,9 +157,32 @@ public final class InternetDomainName {
147157
this.parts = ImmutableList.copyOf(DOT_SPLITTER.split(name));
148158
checkArgument(parts.size() <= MAX_PARTS, "Domain has too many parts: '%s'", name);
149159
checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", name);
160+
}
161+
162+
/**
163+
* The index in the {@link #parts()} list at which the public suffix begins. For example, for the
164+
* domain name {@code myblog.blogspot.co.uk}, the value would be 1 (the index of the {@code
165+
* blogspot} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no public
166+
* suffix was found.
167+
*/
168+
private int publicSuffixIndex() {
169+
if (publicSuffixIndexCache == SUFFIX_NOT_INITIALIZED) {
170+
publicSuffixIndexCache = findSuffixOfType(Optional.<PublicSuffixType>absent());
171+
}
172+
return publicSuffixIndexCache;
173+
}
150174

151-
this.publicSuffixIndex = findSuffixOfType(Optional.<PublicSuffixType>absent());
152-
this.registrySuffixIndex = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY));
175+
/**
176+
* The index in the {@link #parts()} list at which the registry suffix begins. For example, for
177+
* the domain name {@code myblog.blogspot.co.uk}, the value would be 2 (the index of the {@code
178+
* co} part). The value is negative (specifically, {@link #NO_SUFFIX_FOUND}) if no registry suffix
179+
* was found.
180+
*/
181+
private int registrySuffixIndex() {
182+
if (registrySuffixIndexCache == SUFFIX_NOT_INITIALIZED) {
183+
registrySuffixIndexCache = findSuffixOfType(Optional.of(PublicSuffixType.REGISTRY));
184+
}
185+
return registrySuffixIndexCache;
153186
}
154187

155188
/**
@@ -331,7 +364,7 @@ public ImmutableList<String> parts() {
331364
* @since 6.0
332365
*/
333366
public boolean isPublicSuffix() {
334-
return publicSuffixIndex == 0;
367+
return publicSuffixIndex() == 0;
335368
}
336369

337370
/**
@@ -347,7 +380,7 @@ public boolean isPublicSuffix() {
347380
* @since 6.0
348381
*/
349382
public boolean hasPublicSuffix() {
350-
return publicSuffixIndex != NO_SUFFIX_FOUND;
383+
return publicSuffixIndex() != NO_SUFFIX_FOUND;
351384
}
352385

353386
/**
@@ -358,7 +391,7 @@ public boolean hasPublicSuffix() {
358391
*/
359392
@CheckForNull
360393
public InternetDomainName publicSuffix() {
361-
return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null;
394+
return hasPublicSuffix() ? ancestor(publicSuffixIndex()) : null;
362395
}
363396

364397
/**
@@ -374,7 +407,7 @@ public InternetDomainName publicSuffix() {
374407
* @since 6.0
375408
*/
376409
public boolean isUnderPublicSuffix() {
377-
return publicSuffixIndex > 0;
410+
return publicSuffixIndex() > 0;
378411
}
379412

380413
/**
@@ -390,7 +423,7 @@ public boolean isUnderPublicSuffix() {
390423
* @since 6.0
391424
*/
392425
public boolean isTopPrivateDomain() {
393-
return publicSuffixIndex == 1;
426+
return publicSuffixIndex() == 1;
394427
}
395428

396429
/**
@@ -414,7 +447,7 @@ public InternetDomainName topPrivateDomain() {
414447
return this;
415448
}
416449
checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", name);
417-
return ancestor(publicSuffixIndex - 1);
450+
return ancestor(publicSuffixIndex() - 1);
418451
}
419452

420453
/**
@@ -441,7 +474,7 @@ public InternetDomainName topPrivateDomain() {
441474
* @since 23.3
442475
*/
443476
public boolean isRegistrySuffix() {
444-
return registrySuffixIndex == 0;
477+
return registrySuffixIndex() == 0;
445478
}
446479

447480
/**
@@ -456,7 +489,7 @@ public boolean isRegistrySuffix() {
456489
* @since 23.3
457490
*/
458491
public boolean hasRegistrySuffix() {
459-
return registrySuffixIndex != NO_SUFFIX_FOUND;
492+
return registrySuffixIndex() != NO_SUFFIX_FOUND;
460493
}
461494

462495
/**
@@ -467,7 +500,7 @@ public boolean hasRegistrySuffix() {
467500
*/
468501
@CheckForNull
469502
public InternetDomainName registrySuffix() {
470-
return hasRegistrySuffix() ? ancestor(registrySuffixIndex) : null;
503+
return hasRegistrySuffix() ? ancestor(registrySuffixIndex()) : null;
471504
}
472505

473506
/**
@@ -479,7 +512,7 @@ public InternetDomainName registrySuffix() {
479512
* @since 23.3
480513
*/
481514
public boolean isUnderRegistrySuffix() {
482-
return registrySuffixIndex > 0;
515+
return registrySuffixIndex() > 0;
483516
}
484517

485518
/**
@@ -494,7 +527,7 @@ public boolean isUnderRegistrySuffix() {
494527
* @since 23.3
495528
*/
496529
public boolean isTopDomainUnderRegistrySuffix() {
497-
return registrySuffixIndex == 1;
530+
return registrySuffixIndex() == 1;
498531
}
499532

500533
/**
@@ -517,7 +550,7 @@ public InternetDomainName topDomainUnderRegistrySuffix() {
517550
return this;
518551
}
519552
checkState(isUnderRegistrySuffix(), "Not under a registry suffix: %s", name);
520-
return ancestor(registrySuffixIndex - 1);
553+
return ancestor(registrySuffixIndex() - 1);
521554
}
522555

523556
/** Indicates whether this domain is composed of two or more parts. */

0 commit comments

Comments
 (0)
Please sign in to comment.