mirror of
https://github.com/google/nomulus
synced 2026-05-28 10:40:44 +00:00
Compare commits
59 Commits
proxy-2020
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
576c05ff5f | ||
|
|
f52e887db5 | ||
|
|
6ed286e3bc | ||
|
|
93d922af6f | ||
|
|
0b73e9032c | ||
|
|
4d5d9700b8 | ||
|
|
3534a146e4 | ||
|
|
4ec7f23e84 | ||
|
|
7a68b1b6f0 | ||
|
|
14e593d9e1 | ||
|
|
2d5de96fbd | ||
|
|
13d30b0bfb | ||
|
|
b05f6b4ba3 | ||
|
|
17a1387184 | ||
|
|
2e230664fd | ||
|
|
299b093f78 | ||
|
|
61e7fa89f7 | ||
|
|
6ab69d4226 | ||
|
|
0f09a4a0ab | ||
|
|
95f6ccc657 | ||
|
|
77fabe4dc4 | ||
|
|
71fa12f773 | ||
|
|
fd40a6a2b9 | ||
|
|
71f86c9970 | ||
|
|
6f75dfd116 | ||
|
|
ad5a74fee9 | ||
|
|
29b1ec4211 | ||
|
|
553d5717cb | ||
|
|
1056fdbb64 | ||
|
|
4aaf31be9f | ||
|
|
e30c0f9a11 | ||
|
|
2a5d9c8ef5 | ||
|
|
597f5746a4 | ||
|
|
5bff53a711 | ||
|
|
933394e8c3 | ||
|
|
3b841bbb5b | ||
|
|
798879d031 | ||
|
|
1a63d50b82 | ||
|
|
054571a625 | ||
|
|
7468a9915b | ||
|
|
157d9f75c1 | ||
|
|
b2e4f07bb9 | ||
|
|
5488e1b323 | ||
|
|
5ab0f97351 | ||
|
|
f7b65327da | ||
|
|
36482ce94f | ||
|
|
125f509b46 | ||
|
|
fb7ba80b86 | ||
|
|
a86fcf79f7 | ||
|
|
dc8e095e55 | ||
|
|
cdf2c7f7cb | ||
|
|
ecafebdc3d | ||
|
|
c6c8d21281 | ||
|
|
5f6ea2cbf2 | ||
|
|
393c388e0d | ||
|
|
5a08ce498e | ||
|
|
5db8cbc994 | ||
|
|
bbcafea98e | ||
|
|
1bba68dd96 |
@@ -191,7 +191,7 @@ allprojects {
|
||||
}
|
||||
|
||||
task runPresubmits(type: Exec) {
|
||||
executable '/usr/bin/python'
|
||||
executable '/usr/bin/python3'
|
||||
args('config/presubmits.py')
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ subprojects {
|
||||
// in the 'configurations' block, the following code must run after
|
||||
// project evaluation, when all configurations have been created.
|
||||
configurations.each {
|
||||
if (it.name != 'dependencyLicenseReport') {
|
||||
if (it.name != 'dependencyLicenseReport' && it.name != 'integration') {
|
||||
it.resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.time.ZonedDateTime;
|
||||
import java.util.TimeZone;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/** Utilities methods and constants related to Joda {@link DateTime} objects. */
|
||||
public class DateTimeUtils {
|
||||
@@ -108,4 +109,12 @@ public class DateTimeUtils {
|
||||
zonedDateTime.toInstant().toEpochMilli(),
|
||||
DateTimeZone.forTimeZone(TimeZone.getTimeZone(zonedDateTime.getZone())));
|
||||
}
|
||||
|
||||
public static java.sql.Date toSqlDate(LocalDate localDate) {
|
||||
return new java.sql.Date(localDate.toDateTimeAtStartOfDay().getMillis());
|
||||
}
|
||||
|
||||
public static LocalDate toLocalDate(java.sql.Date date) {
|
||||
return new LocalDate(date.getTime(), DateTimeZone.UTC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.inject.Inject;
|
||||
import org.joda.time.ReadableDuration;
|
||||
@@ -41,6 +40,6 @@ public final class SystemSleeper implements Sleeper, Serializable {
|
||||
@Override
|
||||
public void sleepUninterruptibly(ReadableDuration duration) {
|
||||
checkArgument(duration.getMillis() >= 0);
|
||||
Uninterruptibles.sleepUninterruptibly(duration.getMillis(), TimeUnit.MILLISECONDS);
|
||||
Uninterruptibles.sleepUninterruptibly(java.time.Duration.ofMillis(duration.getMillis()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import attr
|
||||
import dataclasses
|
||||
import io
|
||||
import os
|
||||
import shutil
|
||||
@@ -25,7 +25,7 @@ import sys
|
||||
from typing import List, Union
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
@dataclasses.dataclass
|
||||
class Property:
|
||||
name : str = ''
|
||||
desc : str = ''
|
||||
@@ -39,7 +39,7 @@ class Property:
|
||||
raise ValidationError('value of {self.name} must be "true" or '
|
||||
'"false".')
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
@dataclasses.dataclass
|
||||
class GradleFlag:
|
||||
flags : Union[str, List[str]]
|
||||
desc : str
|
||||
@@ -75,6 +75,7 @@ Pseudo-commands:
|
||||
"""
|
||||
|
||||
# Define all of our special gradle properties here.
|
||||
# TODO(b/169318491): use consistent naming style for properties and variables.
|
||||
PROPERTIES = [
|
||||
Property('mavenUrl',
|
||||
'URL to use for the main maven repository (defaults to maven '
|
||||
@@ -124,6 +125,9 @@ PROPERTIES = [
|
||||
'server/schema integration tests. Please refer to <a '
|
||||
'href="./integration/README.md">integration project</a> for more '
|
||||
'information.'),
|
||||
Property('baseSchemaTag',
|
||||
'The nomulus version tag of the schema for use in the schema'
|
||||
'deployment integration test (:db:schemaIncrementalDeployTest)'),
|
||||
Property('schema_version',
|
||||
'The nomulus version tag of the schema for use in a database'
|
||||
'integration test.'),
|
||||
|
||||
@@ -18,6 +18,7 @@ Error Prone) so we must write them manually.
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import List, Tuple
|
||||
import sys
|
||||
import re
|
||||
|
||||
@@ -178,6 +179,90 @@ PRESUBMITS = {
|
||||
"JavaScript files should not include console logging."
|
||||
}
|
||||
|
||||
# Note that this regex only works for one kind of Flyway file. If we want to
|
||||
# start using "R" and "U" files we'll need to update this script.
|
||||
FLYWAY_FILE_RX = re.compile(r'V(\d+)__.*')
|
||||
|
||||
|
||||
def get_seqnum(filename: str, location: str) -> int:
|
||||
"""Extracts the sequence number from a filename."""
|
||||
m = FLYWAY_FILE_RX.match(filename)
|
||||
if m is None:
|
||||
raise ValueError('Illegal Flyway filename: %s in %s' % (filename, location))
|
||||
return int(m.group(1))
|
||||
|
||||
|
||||
def files_by_seqnum(files: List[str], location: str) -> List[Tuple[int, str]]:
|
||||
"""Returns the list of seqnum, filename sorted by sequence number."""
|
||||
return [(get_seqnum(filename, location), filename) for filename in files]
|
||||
|
||||
|
||||
def has_valid_order(indexed_files: List[Tuple[int, str]], location: str) -> bool:
|
||||
"""Verify that sequence numbers are in order without gaps or duplicates.
|
||||
|
||||
Args:
|
||||
files: List of seqnum, filename for a list of Flyway files.
|
||||
location: Where the list of files came from (for error reporting).
|
||||
|
||||
Returns:
|
||||
True if the file list is valid.
|
||||
"""
|
||||
last_index = 0
|
||||
valid = True
|
||||
for seqnum, filename in indexed_files:
|
||||
if seqnum == last_index:
|
||||
print('duplicate Flyway file sequence number found in %s: %s' %
|
||||
(location, filename))
|
||||
valid = False
|
||||
elif seqnum < last_index:
|
||||
print('File %s in %s is out of order.' % (filename, location))
|
||||
valid = False
|
||||
elif seqnum != last_index + 1:
|
||||
print('Missing Flyway sequence number %d in %s. Next file is %s' %
|
||||
(last_index + 1, location, filename))
|
||||
valid = False
|
||||
last_index = seqnum
|
||||
return valid
|
||||
|
||||
|
||||
def verify_flyway_index():
|
||||
"""Verifies that the Flyway index file is in sync with the directory."""
|
||||
success = True
|
||||
|
||||
# Sort the files in the Flyway directory by their sequence number.
|
||||
files = sorted(
|
||||
files_by_seqnum(os.listdir('db/src/main/resources/sql/flyway'),
|
||||
'Flyway directory'))
|
||||
|
||||
# Make sure that there are no gaps and no duplicate sequence numbers in the
|
||||
# files themselves.
|
||||
if not has_valid_order(files, 'Flyway directory'):
|
||||
success = False
|
||||
|
||||
# Remove the sequence numbers and compare against the index file contents.
|
||||
files = [filename[1] for filename in sorted(files)]
|
||||
with open('db/src/main/resources/sql/flyway.txt') as index:
|
||||
indexed_files = index.read().splitlines()
|
||||
if files != indexed_files:
|
||||
unindexed = set(files) - set(indexed_files)
|
||||
if unindexed:
|
||||
print('The following Flyway files are not in flyway.txt: %s' % unindexed)
|
||||
|
||||
nonexistent = set(indexed_files) - set(files)
|
||||
if nonexistent:
|
||||
print('The following files are in flyway.txt but not in the Flyway '
|
||||
'directory: %s' % nonexistent)
|
||||
|
||||
# Do an ordering check on the index file (ignore the result, we're failing
|
||||
# anyway).
|
||||
has_valid_order(files_by_seqnum(indexed_files, 'flyway.txt'), 'flyway.txt')
|
||||
success = False
|
||||
|
||||
if not success:
|
||||
print('Please fix any conflicts and run "./nom_build :db:generateFlywayIndex"')
|
||||
|
||||
return not success
|
||||
|
||||
|
||||
def get_files():
|
||||
for root, dirnames, filenames in os.walk("."):
|
||||
@@ -197,5 +282,10 @@ if __name__ == "__main__":
|
||||
failed = True
|
||||
print("%s had errors: \n %s" % (file, "\n ".join(error_messages)))
|
||||
|
||||
# And now for something completely different: check to see if the Flyway
|
||||
# index is up-to-date. It's quicker to do it here than in the unit tests:
|
||||
# when we put it here it fails fast before all of the tests are run.
|
||||
failed |= verify_flyway_index()
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -63,8 +63,6 @@ def dockerIncompatibleTestPatterns = [
|
||||
// methods, so we exclude the whole test class.
|
||||
"google/registry/tools/params/PathParameterTest.*",
|
||||
"google/registry/persistence/PersistenceModuleTest.*",
|
||||
// This test is failing in docker when using Java 11. The cause is unclear.
|
||||
"google/registry/tools/DomainLockUtilsTest.*",
|
||||
]
|
||||
|
||||
// Tests that conflict with members of both the main test suite and the
|
||||
@@ -223,6 +221,7 @@ dependencies {
|
||||
compile deps['com.jcraft:jsch']
|
||||
testCompile deps['com.thoughtworks.qdox:qdox']
|
||||
compile deps['dnsjava:dnsjava']
|
||||
runtime deps['guru.nidi:graphviz-java-all-j2v8']
|
||||
testCompile deps['io.github.classgraph:classgraph']
|
||||
testRuntime deps['io.github.java-diff-utils:java-diff-utils']
|
||||
testCompile deps['javax.annotation:javax.annotation-api']
|
||||
@@ -247,6 +246,7 @@ dependencies {
|
||||
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
||||
compile deps['org.apache.httpcomponents:httpclient']
|
||||
compile deps['org.apache.httpcomponents:httpcore']
|
||||
runtime deps['org.apache.logging.log4j:log4j-core']
|
||||
testCompile deps['org.apache.sshd:sshd-core']
|
||||
testCompile deps['org.apache.sshd:sshd-scp']
|
||||
testCompile deps['org.apache.sshd:sshd-sftp']
|
||||
@@ -259,6 +259,7 @@ dependencies {
|
||||
compile deps['org.hibernate:hibernate-core']
|
||||
compile deps['org.joda:joda-money']
|
||||
compile deps['org.json:json']
|
||||
compile deps['org.jsoup:jsoup']
|
||||
testCompile deps['org.mortbay.jetty:jetty']
|
||||
compile deps['org.postgresql:postgresql']
|
||||
testCompile deps['org.seleniumhq.selenium:selenium-api']
|
||||
@@ -271,6 +272,10 @@ dependencies {
|
||||
compile deps['org.testcontainers:postgresql']
|
||||
testCompile deps['org.testcontainers:selenium']
|
||||
testCompile deps['org.testcontainers:testcontainers']
|
||||
compile deps['us.fatehi:schemacrawler']
|
||||
compile deps['us.fatehi:schemacrawler-api']
|
||||
compile deps['us.fatehi:schemacrawler-diagram']
|
||||
compile deps['us.fatehi:schemacrawler-tools']
|
||||
compile deps['xerces:xmlParserAPIs']
|
||||
compile deps['xpp3:xpp3']
|
||||
// This dependency must come after javax.mail:mail as it would otherwise
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
@@ -11,11 +11,11 @@ com.google.dagger:dagger-compiler:2.28
|
||||
com.google.dagger:dagger-producers:2.28
|
||||
com.google.dagger:dagger-spi:2.28
|
||||
com.google.dagger:dagger:2.28
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.errorprone:javac-shaded:9-dev-r4023-3
|
||||
com.google.googlejavaformat:google-java-format:1.5
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
@@ -30,11 +30,14 @@ javax.inject:javax.inject:1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
net.ltgt.gradle.incap:incap:0.2
|
||||
org.checkerframework:checker-compat-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.61
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.61
|
||||
org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0
|
||||
org.jetbrains:annotations:13.0
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -202,6 +202,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -225,6 +226,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -200,6 +200,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -222,6 +223,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -246,5 +248,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -130,6 +134,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -177,6 +184,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.12
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -198,11 +206,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -226,6 +237,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -240,6 +252,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.slf4j:slf4j-jdk14:1.7.28
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
@@ -249,7 +263,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -130,6 +134,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -176,6 +183,7 @@ javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -197,11 +205,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -224,6 +235,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -238,6 +250,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.slf4j:slf4j-jdk14:1.7.28
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
@@ -247,7 +261,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
com.google.code.findbugs:jsr305:3.0.2
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
com.google.guava:guava:27.0.1-jre
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|
||||
com.google.j2objc:j2objc-annotations:1.1
|
||||
com.google.protobuf:protobuf-java:3.4.0
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0
|
||||
org.checkerframework:checker-qual:2.5.3
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -202,6 +202,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -225,6 +226,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -249,5 +251,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -201,6 +201,7 @@ org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -224,6 +225,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -248,5 +250,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -129,6 +133,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -176,6 +183,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.12
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -197,11 +205,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -225,6 +236,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -239,6 +251,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
org.testcontainers:jdbc:1.14.3
|
||||
@@ -247,7 +261,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -129,6 +133,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -176,6 +183,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.12
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -197,11 +205,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -225,6 +236,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -239,6 +251,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
org.testcontainers:jdbc:1.14.3
|
||||
@@ -247,7 +261,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -129,6 +133,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -176,6 +183,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.12
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -197,11 +205,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -225,6 +236,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -239,6 +251,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
org.testcontainers:jdbc:1.14.3
|
||||
@@ -247,7 +261,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,6 +6,10 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
@@ -130,6 +134,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.grpc:grpc-all:1.27.2
|
||||
@@ -176,6 +183,7 @@ javax.validation:validation-api:1.0.0.GA
|
||||
javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
net.java.dev.jna:jna:5.5.0
|
||||
@@ -197,11 +205,14 @@ org.apache.beam:beam-vendor-grpc-1_26_0:0.3
|
||||
org.apache.beam:beam-vendor-guava-26_0-jre:0.1
|
||||
org.apache.beam:beam-vendor-sdks-java-extensions-protobuf:2.23.0
|
||||
org.apache.commons:commons-compress:1.20
|
||||
org.apache.commons:commons-exec:1.3
|
||||
org.apache.commons:commons-lang3:3.5
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.bouncycastle:bcpg-jdk15on:1.61
|
||||
org.bouncycastle:bcpkix-jdk15on:1.61
|
||||
org.bouncycastle:bcprov-jdk15on:1.61
|
||||
org.checkerframework:checker-compat-qual:2.5.5
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
@@ -224,6 +235,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.jvnet.staxex:stax-ex:1.8
|
||||
org.mortbay.jetty:jetty-util:6.1.26
|
||||
org.mortbay.jetty:jetty:6.1.26
|
||||
@@ -238,6 +250,8 @@ org.rnorth.duct-tape:duct-tape:1.0.8
|
||||
org.rnorth.visible-assertions:visible-assertions:2.1.2
|
||||
org.rnorth:tcp-unix-socket-proxy:1.0.2
|
||||
org.scijava:native-lib-loader:2.0.2
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.slf4j:slf4j-jdk14:1.7.28
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
@@ -247,7 +261,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0
|
||||
com.github.kevinstern:software-and-algorithms:1.0
|
||||
com.github.stephenc.jcip:jcip-annotations:1.0-1
|
||||
com.google.auto.value:auto-value:1.6.3
|
||||
com.google.auto:auto-common:0.10
|
||||
com.google.code.findbugs:jFormatString:3.0.0
|
||||
@@ -11,11 +11,11 @@ com.google.dagger:dagger-compiler:2.28
|
||||
com.google.dagger:dagger-producers:2.28
|
||||
com.google.dagger:dagger-spi:2.28
|
||||
com.google.dagger:dagger:2.28
|
||||
com.google.errorprone:error_prone_annotation:2.3.3
|
||||
com.google.errorprone:error_prone_annotation:2.3.4
|
||||
com.google.errorprone:error_prone_annotations:2.3.4
|
||||
com.google.errorprone:error_prone_check_api:2.3.3
|
||||
com.google.errorprone:error_prone_core:2.3.3
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.3
|
||||
com.google.errorprone:error_prone_check_api:2.3.4
|
||||
com.google.errorprone:error_prone_core:2.3.4
|
||||
com.google.errorprone:error_prone_type_annotations:2.3.4
|
||||
com.google.errorprone:javac-shaded:9-dev-r4023-3
|
||||
com.google.googlejavaformat:google-java-format:1.5
|
||||
com.google.guava:failureaccess:1.0.1
|
||||
@@ -30,11 +30,14 @@ javax.inject:javax.inject:1
|
||||
javax.persistence:javax.persistence-api:2.2
|
||||
net.ltgt.gradle.incap:incap:0.2
|
||||
org.checkerframework:checker-compat-qual:2.5.3
|
||||
org.checkerframework:checker-qual:2.11.1
|
||||
org.checkerframework:dataflow:2.5.3
|
||||
org.checkerframework:javacutil:2.5.3
|
||||
org.checkerframework:checker-qual:3.0.0
|
||||
org.checkerframework:dataflow:3.0.0
|
||||
org.checkerframework:javacutil:3.0.0
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.61
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.61
|
||||
org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0
|
||||
org.jetbrains:annotations:13.0
|
||||
org.pcollections:pcollections:2.1.2
|
||||
org.plumelib:plume-util:1.0.6
|
||||
org.plumelib:reflection-util:0.0.2
|
||||
org.plumelib:require-javadoc:0.1.0
|
||||
|
||||
@@ -6,9 +6,9 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.11.2
|
||||
com.fasterxml:classmate:1.5.1
|
||||
com.github.jnr:jffi:1.2.23
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -248,6 +248,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.junit-pioneer:junit-pioneer:0.7.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
@@ -298,5 +299,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,9 +6,9 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.11.2
|
||||
com.fasterxml:classmate:1.5.1
|
||||
com.github.jnr:jffi:1.2.23
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -247,6 +247,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.junit-pioneer:junit-pioneer:0.7.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
@@ -297,5 +298,10 @@ org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,9 +6,13 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.11.2
|
||||
com.fasterxml:classmate:1.5.1
|
||||
com.github.jnr:jffi:1.2.23
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -138,6 +142,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.github.java-diff-utils:java-diff-utils:4.0
|
||||
@@ -186,6 +193,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
@@ -216,7 +224,8 @@ org.apache.ftpserver:ftplet-api:1.0.6
|
||||
org.apache.ftpserver:ftpserver-core:1.0.6
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apache.mina:mina-core:2.0.4
|
||||
org.apache.sshd:sshd-core:2.0.0
|
||||
org.apache.sshd:sshd-scp:2.0.0
|
||||
@@ -251,6 +260,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.junit-pioneer:junit-pioneer:0.7.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
@@ -289,6 +299,8 @@ org.seleniumhq.selenium:selenium-opera-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-remote-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-safari-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-support:3.141.59
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
org.testcontainers:jdbc:1.14.3
|
||||
@@ -299,7 +311,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -6,9 +6,13 @@ aopalliance:aopalliance:1.0
|
||||
args4j:args4j:2.33
|
||||
cglib:cglib-nodep:2.2
|
||||
com.beust:jcommander:1.60
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.10.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.10.2
|
||||
com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0
|
||||
com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-core:2.11.2
|
||||
com.fasterxml.jackson.core:jackson-databind:2.11.2
|
||||
com.fasterxml:classmate:1.5.1
|
||||
com.github.jnr:jffi:1.2.23
|
||||
com.github.jnr:jnr-a64asm:1.0.0
|
||||
@@ -138,6 +142,9 @@ com.zaxxer:HikariCP:3.2.0
|
||||
commons-codec:commons-codec:1.13
|
||||
commons-logging:commons-logging:1.2
|
||||
dnsjava:dnsjava:2.1.7
|
||||
guru.nidi.com.kitfox:svgSalamander:1.1.3
|
||||
guru.nidi:graphviz-java-all-j2v8:0.17.0
|
||||
guru.nidi:graphviz-java:0.17.0
|
||||
io.dropwizard.metrics:metrics-core:3.2.6
|
||||
io.github.classgraph:classgraph:4.8.65
|
||||
io.github.java-diff-utils:java-diff-utils:4.0
|
||||
@@ -186,6 +193,7 @@ javax.xml.bind:jaxb-api:2.3.1
|
||||
jline:jline:1.0
|
||||
joda-time:joda-time:2.10.5
|
||||
junit:junit:4.13
|
||||
net.arnx:nashorn-promise:0.1.1
|
||||
net.bytebuddy:byte-buddy-agent:1.10.5
|
||||
net.bytebuddy:byte-buddy:1.10.10
|
||||
net.java.dev.jna:jna-platform:5.5.0
|
||||
@@ -216,7 +224,8 @@ org.apache.ftpserver:ftplet-api:1.0.6
|
||||
org.apache.ftpserver:ftpserver-core:1.0.6
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apache.logging.log4j:log4j-api:2.6.2
|
||||
org.apache.logging.log4j:log4j-api:2.13.3
|
||||
org.apache.logging.log4j:log4j-core:2.13.3
|
||||
org.apache.mina:mina-core:2.0.4
|
||||
org.apache.sshd:sshd-core:2.0.0
|
||||
org.apache.sshd:sshd-scp:2.0.0
|
||||
@@ -251,6 +260,7 @@ org.jboss:jandex:2.1.3.Final
|
||||
org.jetbrains:annotations:19.0.0
|
||||
org.joda:joda-money:1.0.1
|
||||
org.json:json:20160810
|
||||
org.jsoup:jsoup:1.13.1
|
||||
org.junit-pioneer:junit-pioneer:0.7.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
@@ -289,6 +299,8 @@ org.seleniumhq.selenium:selenium-opera-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-remote-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-safari-driver:3.141.59
|
||||
org.seleniumhq.selenium:selenium-support:3.141.59
|
||||
org.slf4j:jcl-over-slf4j:1.7.30
|
||||
org.slf4j:jul-to-slf4j:1.7.30
|
||||
org.slf4j:slf4j-api:1.7.30
|
||||
org.slf4j:slf4j-jdk14:1.7.28
|
||||
org.testcontainers:database-commons:1.14.3
|
||||
@@ -300,7 +312,13 @@ org.testcontainers:testcontainers:1.14.3
|
||||
org.threeten:threetenbp:1.4.1
|
||||
org.tukaani:xz:1.8
|
||||
org.w3c.css:sac:1.3
|
||||
org.webjars.npm:viz.js-for-graphviz-java:2.1.3
|
||||
org.xerial.snappy:snappy-java:1.1.4
|
||||
org.yaml:snakeyaml:1.17
|
||||
us.fatehi:schemacrawler-api:16.10.1
|
||||
us.fatehi:schemacrawler-diagram:16.10.1
|
||||
us.fatehi:schemacrawler-tools:16.10.1
|
||||
us.fatehi:schemacrawler-utility:16.10.1
|
||||
us.fatehi:schemacrawler:16.10.1
|
||||
xerces:xmlParserAPIs:2.6.2
|
||||
xpp3:xpp3:1.1.4c
|
||||
|
||||
@@ -169,16 +169,20 @@ public final class AsyncTaskEnqueuer {
|
||||
lock.getRelockDuration().isPresent(),
|
||||
"Lock with ID %s not configured for relock",
|
||||
lock.getRevisionId());
|
||||
enqueueDomainRelock(lock.getRelockDuration().get(), lock.getRevisionId(), 0);
|
||||
}
|
||||
|
||||
/** Enqueues a task to asynchronously re-lock a registry-locked domain after it was unlocked. */
|
||||
void enqueueDomainRelock(Duration countdown, long lockRevisionId, int previousAttempts) {
|
||||
String backendHostname = appEngineServiceUtils.getServiceHostname("backend");
|
||||
addTaskToQueueWithRetry(
|
||||
asyncActionsPushQueue,
|
||||
TaskOptions.Builder.withUrl(RelockDomainAction.PATH)
|
||||
.method(Method.POST)
|
||||
.header("Host", backendHostname)
|
||||
.param(
|
||||
RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM,
|
||||
String.valueOf(lock.getRevisionId()))
|
||||
.countdownMillis(lock.getRelockDuration().get().getMillis()));
|
||||
.param(RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM, String.valueOf(lockRevisionId))
|
||||
.param(RelockDomainAction.PREVIOUS_ATTEMPTS_PARAM, String.valueOf(previousAttempts))
|
||||
.countdownMillis(countdown.getMillis()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
|
||||
import static google.registry.request.RequestParameters.extractIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractLongParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
|
||||
@@ -94,9 +95,15 @@ public class BatchModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter("oldUnlockRevisionId")
|
||||
@Parameter(RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM)
|
||||
static long provideOldUnlockRevisionId(HttpServletRequest req) {
|
||||
return extractLongParameter(req, "oldUnlockRevisionId");
|
||||
return extractLongParameter(req, RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter(RelockDomainAction.PREVIOUS_ATTEMPTS_PARAM)
|
||||
static int providePreviousAttempts(HttpServletRequest req) {
|
||||
return extractIntParameter(req, RelockDomainAction.PREVIOUS_ATTEMPTS_PARAM);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -464,7 +464,7 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
||||
HostResource host = (HostResource) existingResource;
|
||||
if (host.isSubordinate()) {
|
||||
dnsQueue.addHostRefreshTask(host.getHostName());
|
||||
tm().saveNewOrUpdate(
|
||||
tm().put(
|
||||
tm().load(host.getSuperordinateDomain())
|
||||
.asBuilder()
|
||||
.removeSubordinateHost(host.getHostName())
|
||||
|
||||
@@ -15,19 +15,23 @@
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
@@ -36,11 +40,15 @@ import google.registry.request.auth.Auth;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.tools.DomainLockUtils;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Task that relocks a previously-Registry-Locked domain after some predetermined period of time.
|
||||
*/
|
||||
/** Task that re-locks a previously-Registry-Locked domain after a predetermined period of time. */
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = RelockDomainAction.PATH,
|
||||
@@ -51,30 +59,78 @@ public class RelockDomainAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/relockDomain";
|
||||
public static final String OLD_UNLOCK_REVISION_ID_PARAM = "oldUnlockRevisionId";
|
||||
public static final String PREVIOUS_ATTEMPTS_PARAM = "previousAttempts";
|
||||
|
||||
static final int ATTEMPTS_BEFORE_SLOWDOWN = 36; // every ten minutes for six hours then every hour
|
||||
static final int FAILURES_BEFORE_EMAIL = 2; // email after three failures, one half hour
|
||||
private static final Duration TEN_MINUTES = Duration.standardMinutes(10);
|
||||
private static final Duration ONE_HOUR = Duration.standardHours(1);
|
||||
|
||||
private static final String RELOCK_SUCCESS_EMAIL_TEMPLATE =
|
||||
"The domain %s was successfully re-locked.\n\nPlease contact support at %s if you have any "
|
||||
+ "questions.";
|
||||
private static final String RELOCK_NON_RETRYABLE_FAILURE_EMAIL_TEMPLATE =
|
||||
"There was an error when automatically re-locking %s. Error message: %s\n\nPlease contact "
|
||||
+ "support at %s if you have any questions.";
|
||||
private static final String RELOCK_TRANSIENT_FAILURE_EMAIL_TEMPLATE =
|
||||
"There was an unexpected error when automatically re-locking %s. We will continue retrying "
|
||||
+ "the lock for five hours. Please contact support at %s if you have any questions";
|
||||
private static final String RELOCK_UNKNOWN_ID_FAILURE_EMAIL_TEMPLATE =
|
||||
"The old lock with revision ID %d is not present or is not accessible";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final long oldUnlockRevisionId;
|
||||
private final int previousAttempts;
|
||||
private final InternetAddress alertRecipientAddress;
|
||||
private final InternetAddress gSuiteOutgoingEmailAddress;
|
||||
private final String supportEmail;
|
||||
private final SendEmailService sendEmailService;
|
||||
private final DomainLockUtils domainLockUtils;
|
||||
private final Response response;
|
||||
private final AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
|
||||
@Inject
|
||||
public RelockDomainAction(
|
||||
@Parameter(OLD_UNLOCK_REVISION_ID_PARAM) long oldUnlockRevisionId,
|
||||
@Parameter(PREVIOUS_ATTEMPTS_PARAM) int previousAttempts,
|
||||
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
|
||||
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
|
||||
@Config("supportEmail") String supportEmail,
|
||||
SendEmailService sendEmailService,
|
||||
DomainLockUtils domainLockUtils,
|
||||
Response response) {
|
||||
Response response,
|
||||
AsyncTaskEnqueuer asyncTaskEnqueuer) {
|
||||
this.oldUnlockRevisionId = oldUnlockRevisionId;
|
||||
this.previousAttempts = previousAttempts;
|
||||
this.alertRecipientAddress = alertRecipientAddress;
|
||||
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
|
||||
this.supportEmail = supportEmail;
|
||||
this.sendEmailService = sendEmailService;
|
||||
this.domainLockUtils = domainLockUtils;
|
||||
this.response = response;
|
||||
this.asyncTaskEnqueuer = asyncTaskEnqueuer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
jpaTm().transact(this::relockDomain);
|
||||
/* We wish to manually control our retry behavior, in order to limit the number of retries
|
||||
* and/or notify registrars / support only after a certain number of retries, or only
|
||||
* with a certain type of failure. AppEngine will automatically retry on any non-2xx status
|
||||
* code, so return SC_NO_CONTENT (204) by default to avoid this auto-retry.
|
||||
*
|
||||
* See https://cloud.google.com/appengine/docs/standard/java/taskqueue/push/retrying-tasks
|
||||
* for more details on retry behavior. */
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
|
||||
// nb: DomainLockUtils relies on the JPA transaction being the outermost transaction
|
||||
jpaTm().transact(() -> tm().transact(this::relockDomain));
|
||||
}
|
||||
|
||||
private void relockDomain() {
|
||||
RegistryLock oldLock;
|
||||
RegistryLock oldLock = null;
|
||||
DomainBase domain;
|
||||
try {
|
||||
oldLock =
|
||||
RegistryLockDao.getByRevisionId(oldUnlockRevisionId)
|
||||
@@ -82,87 +138,187 @@ public class RelockDomainAction implements Runnable {
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format("Unknown revision ID %d", oldUnlockRevisionId)));
|
||||
DomainBase domain =
|
||||
domain =
|
||||
ofy()
|
||||
.load()
|
||||
.type(DomainBase.class)
|
||||
.id(oldLock.getRepoId())
|
||||
.now()
|
||||
.cloneProjectedAtTime(jpaTm().getTransactionTime());
|
||||
|
||||
if (domain.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES)
|
||||
|| oldLock.getRelock() != null) {
|
||||
// The domain was manually locked, so we shouldn't worry about relocking
|
||||
String message =
|
||||
String.format(
|
||||
"Domain %s is already manually relocked, skipping automated relock.",
|
||||
domain.getDomainName());
|
||||
logger.atInfo().log(message);
|
||||
// SC_NO_CONTENT (204) skips retry -- see the comment below
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload(message);
|
||||
return;
|
||||
}
|
||||
verifyDomainAndLockState(oldLock, domain);
|
||||
} catch (Throwable t) {
|
||||
/* If there's a bad verification code or the domain is in a bad state, we won't want to retry.
|
||||
* AppEngine will retry on non-2xx error codes, so we return SC_NO_CONTENT (204) to avoid it.
|
||||
*
|
||||
* See https://cloud.google.com/appengine/docs/standard/java/taskqueue/push/retrying-tasks
|
||||
* for more details on retry behavior. */
|
||||
logger.atWarning().withCause(t).log(
|
||||
"Exception when attempting to relock domain with old revision ID %d.",
|
||||
oldUnlockRevisionId);
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
|
||||
handleTransientFailure(Optional.ofNullable(oldLock), t);
|
||||
return;
|
||||
}
|
||||
applyRelock(oldLock);
|
||||
|
||||
if (domain.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES)
|
||||
|| oldLock.getRelock() != null) {
|
||||
// The domain was manually locked, so we shouldn't worry about re-locking
|
||||
String message =
|
||||
String.format(
|
||||
"Domain %s is already manually re-locked, skipping automated re-lock.",
|
||||
domain.getDomainName());
|
||||
logger.atInfo().log(message);
|
||||
response.setPayload(message);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
verifyDomainAndLockState(oldLock, domain);
|
||||
} catch (Throwable t) {
|
||||
// If the domain was, for example, transferred, then notify the old registrar and don't retry.
|
||||
handleNonRetryableFailure(oldLock, t);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
applyRelock(oldLock);
|
||||
} catch (Throwable t) {
|
||||
handleTransientFailure(Optional.of(oldLock), t);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyRelock(RegistryLock oldLock) {
|
||||
try {
|
||||
domainLockUtils.administrativelyApplyLock(
|
||||
oldLock.getDomainName(),
|
||||
oldLock.getRegistrarId(),
|
||||
oldLock.getRegistrarPocId(),
|
||||
oldLock.isSuperuser());
|
||||
logger.atInfo().log("Relocked domain %s.", oldLock.getDomainName());
|
||||
response.setStatus(SC_OK);
|
||||
} catch (Throwable t) {
|
||||
// Any errors that occur here are unexpected, so we should retry. Return a non-2xx
|
||||
// error code to get AppEngine to retry
|
||||
logger.atSevere().withCause(t).log(
|
||||
"Exception when attempting to relock domain %s.", oldLock.getDomainName());
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
|
||||
domainLockUtils.administrativelyApplyLock(
|
||||
oldLock.getDomainName(),
|
||||
oldLock.getRegistrarId(),
|
||||
oldLock.getRegistrarPocId(),
|
||||
oldLock.isSuperuser());
|
||||
logger.atInfo().log("Re-locked domain %s.", oldLock.getDomainName());
|
||||
response.setStatus(SC_OK);
|
||||
// Only send a success email if we previously sent a failure email
|
||||
if (previousAttempts > FAILURES_BEFORE_EMAIL) {
|
||||
sendSuccessEmail(oldLock);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyDomainAndLockState(RegistryLock oldLock, DomainBase domain) {
|
||||
// Domain shouldn't be deleted or have a pending transfer/delete
|
||||
String domainName = domain.getDomainName();
|
||||
checkArgument(
|
||||
!DateTimeUtils.isAtOrAfter(jpaTm().getTransactionTime(), domain.getDeletionTime()),
|
||||
"Domain %s has been deleted",
|
||||
domainName);
|
||||
ImmutableSet<StatusValue> statusValues = domain.getStatusValues();
|
||||
checkArgument(
|
||||
!statusValues.contains(StatusValue.PENDING_DELETE),
|
||||
"Domain %s has a pending delete",
|
||||
"Domain %s has a pending delete.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
!DateTimeUtils.isAtOrAfter(jpaTm().getTransactionTime(), domain.getDeletionTime()),
|
||||
"Domain %s has been deleted.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
!statusValues.contains(StatusValue.PENDING_TRANSFER),
|
||||
"Domain %s has a pending transfer",
|
||||
"Domain %s has a pending transfer.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
domain.getCurrentSponsorClientId().equals(oldLock.getRegistrarId()),
|
||||
"Domain %s has been transferred from registrar %s to registrar %s since the unlock",
|
||||
"Domain %s has been transferred from registrar %s to registrar %s since the unlock.",
|
||||
domainName,
|
||||
oldLock.getRegistrarId(),
|
||||
domain.getCurrentSponsorClientId());
|
||||
}
|
||||
|
||||
private void handleNonRetryableFailure(RegistryLock oldLock, Throwable t) {
|
||||
logger.atWarning().withCause(t).log(
|
||||
"Exception thrown when attempting to re-lock domain with old revision ID %d.",
|
||||
oldUnlockRevisionId);
|
||||
response.setPayload(String.format("Re-lock failed: %s", t.getMessage()));
|
||||
|
||||
String body =
|
||||
String.format(
|
||||
RELOCK_NON_RETRYABLE_FAILURE_EMAIL_TEMPLATE,
|
||||
oldLock.getDomainName(),
|
||||
t.getMessage(),
|
||||
supportEmail);
|
||||
sendEmailService.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(gSuiteOutgoingEmailAddress)
|
||||
.setBody(body)
|
||||
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
|
||||
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
|
||||
.build());
|
||||
}
|
||||
|
||||
private void handleTransientFailure(Optional<RegistryLock> oldLock, Throwable t) {
|
||||
String message = String.format("Re-lock failed: %s", t.getMessage());
|
||||
logger.atSevere().withCause(t).log(message);
|
||||
response.setPayload(message);
|
||||
|
||||
if (previousAttempts == FAILURES_BEFORE_EMAIL) {
|
||||
if (oldLock.isPresent()) {
|
||||
sendGenericTransientFailureEmail(oldLock.get());
|
||||
} else {
|
||||
// if the old lock isn't present, something has gone horribly wrong
|
||||
sendUnknownRevisionIdAlertEmail();
|
||||
}
|
||||
}
|
||||
Duration timeBeforeRetry = previousAttempts < ATTEMPTS_BEFORE_SLOWDOWN ? TEN_MINUTES : ONE_HOUR;
|
||||
asyncTaskEnqueuer.enqueueDomainRelock(
|
||||
timeBeforeRetry, oldUnlockRevisionId, previousAttempts + 1);
|
||||
}
|
||||
|
||||
private void sendSuccessEmail(RegistryLock oldLock) {
|
||||
String body =
|
||||
String.format(RELOCK_SUCCESS_EMAIL_TEMPLATE, oldLock.getDomainName(), supportEmail);
|
||||
|
||||
sendEmailService.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(gSuiteOutgoingEmailAddress)
|
||||
.setBody(body)
|
||||
.setSubject(String.format("Successful re-lock of domain %s", oldLock.getDomainName()))
|
||||
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
|
||||
.build());
|
||||
}
|
||||
|
||||
private void sendGenericTransientFailureEmail(RegistryLock oldLock) {
|
||||
String body =
|
||||
String.format(
|
||||
RELOCK_TRANSIENT_FAILURE_EMAIL_TEMPLATE, oldLock.getDomainName(), supportEmail);
|
||||
// For an unexpected failure, notify both the lock-enabled contacts and our alerting email
|
||||
ImmutableSet<InternetAddress> allRecipients =
|
||||
new ImmutableSet.Builder<InternetAddress>()
|
||||
.addAll(getEmailRecipients(oldLock.getRegistrarId()))
|
||||
.add(alertRecipientAddress)
|
||||
.build();
|
||||
sendEmailService.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(gSuiteOutgoingEmailAddress)
|
||||
.setBody(body)
|
||||
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
|
||||
.setRecipients(allRecipients)
|
||||
.build());
|
||||
}
|
||||
|
||||
private void sendUnknownRevisionIdAlertEmail() {
|
||||
sendEmailService.sendEmail(
|
||||
EmailMessage.newBuilder()
|
||||
.setFrom(gSuiteOutgoingEmailAddress)
|
||||
.setBody(String.format(RELOCK_UNKNOWN_ID_FAILURE_EMAIL_TEMPLATE, oldUnlockRevisionId))
|
||||
.setSubject("Error re-locking domain")
|
||||
.setRecipients(ImmutableSet.of(alertRecipientAddress))
|
||||
.build());
|
||||
}
|
||||
|
||||
private ImmutableSet<InternetAddress> getEmailRecipients(String registrarId) {
|
||||
Registrar registrar =
|
||||
Registrar.loadByClientIdCached(registrarId)
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalStateException(String.format("Unknown registrar %s", registrarId)));
|
||||
|
||||
ImmutableSet<String> registryLockEmailAddresses =
|
||||
registrar.getContacts().stream()
|
||||
.filter(RegistrarContact::isRegistryLockAllowed)
|
||||
.map(RegistrarContact::getRegistryLockEmailAddress)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.collect(toImmutableSet());
|
||||
|
||||
ImmutableSet.Builder<InternetAddress> builder = new ImmutableSet.Builder<>();
|
||||
// can't use streams due to the 'throws' in the InternetAddress constructor
|
||||
for (String registryLockEmailAddress : registryLockEmailAddresses) {
|
||||
try {
|
||||
builder.add(new InternetAddress(registryLockEmailAddress));
|
||||
} catch (AddressException e) {
|
||||
// This shouldn't stop any other emails going out, so swallow it
|
||||
logger.atWarning().log("Invalid email address %s", registryLockEmailAddress);
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ public final class Transforms {
|
||||
.map(Optional::get)
|
||||
.map(ofy::toPojo)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
retry(() -> jpaTm().transact(() -> jpaTm().saveNewOrUpdateAll(ofyEntities)));
|
||||
retry(() -> jpaTm().transact(() -> jpaTm().putAll(ofyEntities)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,7 @@ FROM (
|
||||
FROM
|
||||
`%PROJECT_ID%.%DATASTORE_EXPORT_DATA_SET%.%REGISTRY_TABLE%`
|
||||
WHERE
|
||||
-- TODO(b/18092292): Add a filter for tldState (not PDT/PREDELEGATION)
|
||||
tldType = 'REAL'
|
||||
AND disableInvoicing is not TRUE) ) AS BillingEvent
|
||||
invoicingEnabled IS TRUE) ) AS BillingEvent
|
||||
-- Gather billing ID from registrar table
|
||||
-- This is a 'JOIN' as opposed to 'LEFT JOIN' to filter out
|
||||
-- non-billable registrars
|
||||
|
||||
@@ -215,7 +215,7 @@ public class Spec11Pipeline implements Serializable {
|
||||
.setRegistrarId(subdomain.registrarId())
|
||||
.build();
|
||||
JpaTransactionManager jpaTransactionManager = jpaSupplierFactory.get();
|
||||
jpaTransactionManager.transact(() -> jpaTransactionManager.saveNew(threatMatch));
|
||||
jpaTransactionManager.transact(() -> jpaTransactionManager.insert(threatMatch));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.config;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.CertificateChecker;
|
||||
import google.registry.util.Clock;
|
||||
import javax.inject.Singleton;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Dagger module that provides the {@link CertificateChecker} used in the application. */
|
||||
// TODO(sarahbot@): Move this module to a better location. Possibly flows/. If we decide to move
|
||||
// CertificateChecker.java to core/ delete this file and inject the CertificateChecker constructor
|
||||
// instead.
|
||||
@Module
|
||||
public abstract class CertificateCheckerModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static CertificateChecker provideCertificateChecker(
|
||||
@Config("maxValidityDaysSchedule") ImmutableSortedMap<DateTime, Integer> validityDaysMap,
|
||||
@Config("expirationWarningDays") int daysToExpiration,
|
||||
@Config("minimumRsaKeyLength") int minimumRsaKeyLength,
|
||||
Clock clock) {
|
||||
return new CertificateChecker(validityDaysMap, daysToExpiration, minimumRsaKeyLength, clock);
|
||||
}
|
||||
|
||||
private CertificateCheckerModule() {}
|
||||
}
|
||||
@@ -16,9 +16,12 @@ package google.registry.config;
|
||||
|
||||
import static com.google.common.base.Suppliers.memoize;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap;
|
||||
import static google.registry.config.ConfigUtils.makeUrl;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Ascii;
|
||||
@@ -27,6 +30,7 @@ import com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.util.TaskQueueUtils;
|
||||
@@ -46,6 +50,7 @@ import javax.inject.Qualifier;
|
||||
import javax.inject.Singleton;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeConstants;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
@@ -1345,6 +1350,33 @@ public final class RegistryConfig {
|
||||
public static String provideRdapTosStaticUrl(RegistryConfigSettings config) {
|
||||
return config.registryPolicy.rdapTosStaticUrl;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("maxValidityDaysSchedule")
|
||||
public static ImmutableSortedMap<DateTime, Integer> provideValidityDaysMap(
|
||||
RegistryConfigSettings config) {
|
||||
return config.sslCertificateValidation.maxValidityDaysSchedule.entrySet().stream()
|
||||
.collect(
|
||||
toImmutableSortedMap(
|
||||
naturalOrder(),
|
||||
e ->
|
||||
e.getKey().equals("START_OF_TIME")
|
||||
? START_OF_TIME
|
||||
: DateTime.parse(e.getKey()),
|
||||
e -> e.getValue()));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("expirationWarningDays")
|
||||
public static int provideDaysToExpiration(RegistryConfigSettings config) {
|
||||
return config.sslCertificateValidation.expirationWarningDays;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("minimumRsaKeyLength")
|
||||
public static int provideMinimumRsaKeyLength(RegistryConfigSettings config) {
|
||||
return config.sslCertificateValidation.minimumRsaKeyLength;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the App Engine project ID, which is based off the environment name. */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** The POJO that YAML config files are deserialized into. */
|
||||
public class RegistryConfigSettings {
|
||||
@@ -38,6 +39,7 @@ public class RegistryConfigSettings {
|
||||
public Beam beam;
|
||||
public Keyring keyring;
|
||||
public RegistryTool registryTool;
|
||||
public SslCertificateValidation sslCertificateValidation;
|
||||
|
||||
/** Configuration options that apply to the entire App Engine project. */
|
||||
public static class AppEngine {
|
||||
@@ -218,4 +220,11 @@ public class RegistryConfigSettings {
|
||||
public String clientSecret;
|
||||
public String username;
|
||||
}
|
||||
|
||||
/** Configuration for the certificate checker. */
|
||||
public static class SslCertificateValidation {
|
||||
public Map<String, Integer> maxValidityDaysSchedule;
|
||||
public int expirationWarningDays;
|
||||
public int minimumRsaKeyLength;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,3 +446,17 @@ registryTool:
|
||||
# OAuth client secret used by the tool.
|
||||
clientSecret: YOUR_CLIENT_SECRET
|
||||
username: toolusername
|
||||
|
||||
# Configuration options for checking SSL certificates.
|
||||
sslCertificateValidation:
|
||||
# A map specifying the maximum amount of days the certificate can be valid.
|
||||
# The entry key is the date closest before the date the certificate was issued
|
||||
# and the entry value is the applicable maximum validity days for that certificate.
|
||||
maxValidityDaysSchedule:
|
||||
"START_OF_TIME": 825
|
||||
"2020-09-01T00:00:00Z": 398
|
||||
# The number of days before a certificate expires that indicates the
|
||||
# certificate is nearing expiration and warnings should be sent.
|
||||
expirationWarningDays: 30
|
||||
# The minimum number of bits an RSA key must contain
|
||||
minimumRsaKeyLength: 2048
|
||||
|
||||
@@ -173,7 +173,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||
existingDomain, newExpirationTime, autorenewEvent, autorenewPollMessage, now, clientId);
|
||||
updateForeignKeyIndexDeletionTime(newDomain);
|
||||
entitiesToSave.add(newDomain, historyEntry, autorenewEvent, autorenewPollMessage);
|
||||
tm().saveNewOrUpdateAll(entitiesToSave.build());
|
||||
tm().putAll(entitiesToSave.build());
|
||||
tm().delete(existingDomain.getDeletePollMessage());
|
||||
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
|
||||
return responseBuilder
|
||||
|
||||
@@ -67,6 +67,7 @@ import google.registry.model.domain.DomainCommand.Update.AddRemove;
|
||||
import google.registry.model.domain.DomainCommand.Update.Change;
|
||||
import google.registry.model.domain.fee.FeeUpdateCommandExtension;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
import google.registry.model.domain.superuser.DomainUpdateSuperuserExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
@@ -238,10 +239,16 @@ public final class DomainUpdateFlow implements TransactionalFlow {
|
||||
DomainBase.Builder domainBuilder =
|
||||
domain
|
||||
.asBuilder()
|
||||
// Handle the secDNS extension.
|
||||
// Handle the secDNS extension. As dsData in secDnsUpdate is read from EPP input and
|
||||
// does not have domainRepoId set, we create a copy of the existing dsData without
|
||||
// domainRepoId for comparison.
|
||||
.setDsData(
|
||||
secDnsUpdate.isPresent()
|
||||
? updateDsData(domain.getDsData(), secDnsUpdate.get())
|
||||
? updateDsData(
|
||||
domain.getDsData().stream()
|
||||
.map(DelegationSignerData::cloneWithoutDomainRepoId)
|
||||
.collect(toImmutableSet()),
|
||||
secDnsUpdate.get())
|
||||
: domain.getDsData())
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateClientId(clientId)
|
||||
|
||||
@@ -285,7 +285,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
&& newHost.isSubordinate()
|
||||
&& Objects.equals(
|
||||
existingHost.getSuperordinateDomain(), newHost.getSuperordinateDomain())) {
|
||||
tm().saveNewOrUpdate(
|
||||
tm().put(
|
||||
tm().load(existingHost.getSuperordinateDomain())
|
||||
.asBuilder()
|
||||
.removeSubordinateHost(existingHost.getHostName())
|
||||
@@ -294,14 +294,14 @@ public final class HostUpdateFlow implements TransactionalFlow {
|
||||
return;
|
||||
}
|
||||
if (existingHost.isSubordinate()) {
|
||||
tm().saveNewOrUpdate(
|
||||
tm().put(
|
||||
tm().load(existingHost.getSuperordinateDomain())
|
||||
.asBuilder()
|
||||
.removeSubordinateHost(existingHost.getHostName())
|
||||
.build());
|
||||
}
|
||||
if (newHost.isSubordinate()) {
|
||||
tm().saveNewOrUpdate(
|
||||
tm().put(
|
||||
tm().load(newHost.getSuperordinateDomain())
|
||||
.asBuilder()
|
||||
.addSubordinateHost(newHost.getHostName())
|
||||
|
||||
@@ -64,7 +64,7 @@ public final class PollFlowUtils {
|
||||
// and re-save it for future autorenew poll messages to be delivered. Otherwise, this
|
||||
// autorenew poll message has no more events to deliver and should be deleted.
|
||||
if (nextEventTime.isBefore(autorenewPollMessage.getAutorenewEndTime())) {
|
||||
tm().saveNewOrUpdate(autorenewPollMessage.asBuilder().setEventTime(nextEventTime).build());
|
||||
tm().put(autorenewPollMessage.asBuilder().setEventTime(nextEventTime).build());
|
||||
includeAckedMessageInCount = isBeforeOrAt(nextEventTime, tm().getTransactionTime());
|
||||
} else {
|
||||
tm().delete(autorenewPollMessage.createVKey());
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Arab
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Armn
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Beng
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# Registry: Charleston Road Registry Inc.
|
||||
# Script: Chinese
|
||||
# Script: zh-Hans
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
#
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
# Notes: This table describes codepoints allowed for the Chinese script.
|
||||
|
||||
Reference 0 Unicode 3.2
|
||||
Reference 1 A Complete Set of Simplified Chinese Characters
|
||||
Reference 2 Chinese Variants Collation Table
|
||||
Reference 3 Chinese Big Dictionary
|
||||
Reference 4 Chinese Relationship Table for Unihan Project
|
||||
Reference 5 GB2312
|
||||
Reference 6 General Table for Modern Chinese
|
||||
Reference 7 International Chinese Standard Big Dictionary
|
||||
Reference 8 Unihan Database
|
||||
Reference 9 BIG5
|
||||
# Reference 0 Unicode 3.2
|
||||
# Reference 1 A Complete Set of Simplified Chinese Characters
|
||||
# Reference 2 Chinese Variants Collation Table
|
||||
# Reference 3 Chinese Big Dictionary
|
||||
# Reference 4 Chinese Relationship Table for Unihan Project
|
||||
# Reference 5 GB2312
|
||||
# Reference 6 General Table for Modern Chinese
|
||||
# Reference 7 International Chinese Standard Big Dictionary
|
||||
# Reference 8 Unihan Database
|
||||
# Reference 9 BIG5
|
||||
|
||||
U+002D(0);U+002D(0);
|
||||
U+0030(0);U+0030(0);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Cyrl
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Deva
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Ethi
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Script: Grek
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Script: Guru
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Hebr
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Knda
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Khmr
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
#
|
||||
# Telephone: +1 (650) 253-0000
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Kore
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Mlym
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
#
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Orya
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Sinh
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Taml
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Telu
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Thai
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Script: Tibt
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
# Registry: Charleston Road Registry Inc.
|
||||
# Script: Traditional Chinese
|
||||
# Script: zh-Hant
|
||||
# Version: 1.0
|
||||
# Effective Date: 04-12-2012
|
||||
# Contact: tas-contact.google.com
|
||||
# Contact: iana-contact@google.com
|
||||
# Address: 1600 Amphitheatre Parkway Mountain View, CA 94043, USA
|
||||
# Telephone: +1 (650) 253-0000
|
||||
# Website: www.google.com
|
||||
# Notes: This table describes codepoints allowed for the Traditional Chinese script.
|
||||
|
||||
Reference 0 Unicode 3.2
|
||||
Reference 1 A Complete Set of Simplified Chinese Characters
|
||||
Reference 2 Chinese Variants Collation Table
|
||||
Reference 3 Chinese Big Dictionary
|
||||
Reference 4 Chinese Relationship Table for Unihan Project
|
||||
Reference 5 GB2312
|
||||
Reference 6 General Table for Modern Chinese
|
||||
Reference 7 International Chinese Standard Big Dictionary
|
||||
Reference 8 Unihan Database
|
||||
Reference 9 BIG5
|
||||
# Reference 0 Unicode 3.2
|
||||
# Reference 1 A Complete Set of Simplified Chinese Characters
|
||||
# Reference 2 Chinese Variants Collation Table
|
||||
# Reference 3 Chinese Big Dictionary
|
||||
# Reference 4 Chinese Relationship Table for Unihan Project
|
||||
# Reference 5 GB2312
|
||||
# Reference 6 General Table for Modern Chinese
|
||||
# Reference 7 International Chinese Standard Big Dictionary
|
||||
# Reference 8 Unihan Database
|
||||
# Reference 9 BIG5
|
||||
|
||||
U+002D(0);U+002D(0);
|
||||
U+0030(0);U+0030(0);
|
||||
|
||||
@@ -24,7 +24,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
@@ -62,23 +61,32 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
/**
|
||||
* Unique identifier in the registry for this resource.
|
||||
*
|
||||
* <p>Not persisted so that we can store these in references to other objects. Subclasses that
|
||||
* wish to use this as the primary key should create a getter method annotated with @Id
|
||||
*
|
||||
* <p>This is in the (\w|_){1,80}-\w{1,8} format specified by RFC 5730 for roidType.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
|
||||
*/
|
||||
@Id
|
||||
// not persisted so that we can store these in references to other objects. Subclasses that wish
|
||||
// to use this as the primary key should create a getter method annotated with @Id
|
||||
@Transient
|
||||
String repoId;
|
||||
@Id @Transient String repoId;
|
||||
|
||||
/** The ID of the registrar that is currently sponsoring this resource. */
|
||||
/**
|
||||
* The ID of the registrar that is currently sponsoring this resource.
|
||||
*
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@Index
|
||||
@Column(name = "currentSponsorRegistrarId", nullable = false)
|
||||
@Column(name = "currentSponsorRegistrarId")
|
||||
String currentSponsorClientId;
|
||||
|
||||
/** The ID of the registrar that created this resource. */
|
||||
@Column(name = "creationRegistrarId", nullable = false)
|
||||
/**
|
||||
* The ID of the registrar that created this resource.
|
||||
*
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@Column(name = "creationRegistrarId")
|
||||
String creationClientId;
|
||||
|
||||
/**
|
||||
@@ -91,13 +99,17 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
@Column(name = "lastEppUpdateRegistrarId")
|
||||
String lastEppUpdateClientId;
|
||||
|
||||
/** The time when this resource was created. */
|
||||
// Map the method to XML, not the field, because if we map the field (with an adaptor class) it
|
||||
// will never be omitted from the xml even if the timestamp inside creationTime is null and we
|
||||
// return null from the adaptor. (Instead it gets written as an empty tag.)
|
||||
@Column(nullable = false)
|
||||
@Index
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
/**
|
||||
* The time when this resource was created.
|
||||
*
|
||||
* <p>Map the method to XML, not the field, because if we map the field (with an adaptor class) it
|
||||
* will never be omitted from the xml even if the timestamp inside creationTime is null and we
|
||||
* return null from the adaptor (instead it gets written as an empty tag).
|
||||
*
|
||||
* <p>This can be null in the case of pre-Registry-3.0-migration history objects with null
|
||||
* resource fields.
|
||||
*/
|
||||
@Index CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/**
|
||||
* The time when this resource was or will be deleted.
|
||||
@@ -112,8 +124,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
* out of the index at that time, as long as we query for resources whose deletion time is before
|
||||
* now.
|
||||
*/
|
||||
@Index
|
||||
DateTime deletionTime;
|
||||
@Index DateTime deletionTime;
|
||||
|
||||
/**
|
||||
* The time that this resource was last updated.
|
||||
@@ -144,7 +155,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
return repoId;
|
||||
}
|
||||
|
||||
// Hibernate needs this to populate the repo ID, but no one else should ever use it
|
||||
/** This method exists solely to satisfy Hibernate. Use {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setRepoId(String repoId) {
|
||||
this.repoId = repoId;
|
||||
@@ -375,7 +386,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||
private static LoadingCache<VKey<? extends EppResource>, EppResource> createEppResourcesCache(
|
||||
Duration expiry) {
|
||||
return CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(expiry.getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(java.time.Duration.ofMillis(expiry.getMillis()))
|
||||
.maximumSize(getEppResourceMaxCachedEntries())
|
||||
.build(CACHE_LOADER);
|
||||
}
|
||||
|
||||
@@ -252,7 +252,8 @@ public final class OteAccountBuilder {
|
||||
private void saveAllEntities() {
|
||||
tm().assertInTransaction();
|
||||
|
||||
ImmutableList<Registry> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
// use ImmutableObject instead of Registry so that the Key generation doesn't break
|
||||
ImmutableList<ImmutableObject> registries = ImmutableList.of(sunriseTld, gaTld, eapTld);
|
||||
ImmutableList<RegistrarContact> contacts = contactsBuilder.build();
|
||||
|
||||
if (!replaceExisting) {
|
||||
|
||||
@@ -59,25 +59,11 @@ public class OteStats {
|
||||
|
||||
private OteStats() {}
|
||||
|
||||
private static final Predicate<EppInput> HAS_CLAIMS_NOTICE =
|
||||
eppInput -> {
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
return launchCreate.isPresent() && launchCreate.get().getNotice() != null;
|
||||
};
|
||||
|
||||
private static final Predicate<EppInput> HAS_SEC_DNS =
|
||||
eppInput ->
|
||||
eppInput.getSingleExtension(SecDnsCreateExtension.class).isPresent()
|
||||
|| eppInput.getSingleExtension(SecDnsUpdateExtension.class).isPresent();
|
||||
|
||||
private static final Predicate<EppInput> IS_SUNRISE =
|
||||
eppInput -> {
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
return launchCreate.isPresent() && !isNullOrEmpty(launchCreate.get().getSignedMarks());
|
||||
};
|
||||
|
||||
private static final Predicate<EppInput> IS_IDN =
|
||||
eppInput ->
|
||||
((DomainCommand.Create)
|
||||
@@ -94,6 +80,18 @@ public class OteStats {
|
||||
.getResourceCommand())
|
||||
.getInetAddresses());
|
||||
|
||||
private static boolean hasClaimsNotice(EppInput eppInput) {
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
return launchCreate.isPresent() && launchCreate.get().getNotice() != null;
|
||||
}
|
||||
|
||||
private static boolean isSunrise(EppInput eppInput) {
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
return launchCreate.isPresent() && !isNullOrEmpty(launchCreate.get().getSignedMarks());
|
||||
}
|
||||
|
||||
/** Enum defining the distinct statistics (types of registrar actions) to record. */
|
||||
public enum StatType {
|
||||
CONTACT_CREATES(0, equalTo(Type.CONTACT_CREATE)),
|
||||
@@ -107,8 +105,8 @@ public class OteStats {
|
||||
DOMAIN_CREATES(0, equalTo(Type.DOMAIN_CREATE)),
|
||||
DOMAIN_CREATES_ASCII(1, equalTo(Type.DOMAIN_CREATE), IS_IDN.negate()),
|
||||
DOMAIN_CREATES_IDN(1, equalTo(Type.DOMAIN_CREATE), IS_IDN),
|
||||
DOMAIN_CREATES_START_DATE_SUNRISE(1, equalTo(Type.DOMAIN_CREATE), IS_SUNRISE),
|
||||
DOMAIN_CREATES_WITH_CLAIMS_NOTICE(1, equalTo(Type.DOMAIN_CREATE), HAS_CLAIMS_NOTICE),
|
||||
DOMAIN_CREATES_START_DATE_SUNRISE(1, equalTo(Type.DOMAIN_CREATE), OteStats::isSunrise),
|
||||
DOMAIN_CREATES_WITH_CLAIMS_NOTICE(1, equalTo(Type.DOMAIN_CREATE), OteStats::hasClaimsNotice),
|
||||
DOMAIN_CREATES_WITH_FEE(
|
||||
1,
|
||||
equalTo(Type.DOMAIN_CREATE),
|
||||
|
||||
@@ -33,12 +33,14 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.TimeOfYear;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
@@ -46,6 +48,7 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithLongVKey;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -56,16 +59,14 @@ import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** A billable event in a domain's lifecycle. */
|
||||
@MappedSuperclass
|
||||
@WithLongVKey
|
||||
public abstract class BillingEvent extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity {
|
||||
|
||||
@@ -107,10 +108,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
/** Entity id. */
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
@Id @javax.persistence.Id Long id;
|
||||
|
||||
@Parent @DoNotHydrate @Transient Key<HistoryEntry> parent;
|
||||
|
||||
@@ -148,6 +146,21 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@Nullable
|
||||
Set<Flag> flags;
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(DomainBase.class, domainRepoId),
|
||||
HistoryEntry.class,
|
||||
domainHistoryRevisionId);
|
||||
}
|
||||
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
domainHistoryRevisionId = parent.getId();
|
||||
domainRepoId = parent.getParent().getName();
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
@@ -244,7 +257,6 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public B setParent(Key<HistoryEntry> parentKey) {
|
||||
// TODO(shicong): Figure out how to set domainHistoryRevisionId and domainRepoId
|
||||
getInstance().parent = parentKey;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
@@ -257,6 +269,11 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
checkNotNull(instance.eventTime, "Event time must be set");
|
||||
checkNotNull(instance.targetId, "Target ID must be set");
|
||||
checkNotNull(instance.parent, "Parent must be set");
|
||||
checkNotNull(instance.parent.getParent(), "parent.getParent() must be set");
|
||||
checkNotNull(
|
||||
instance.parent.getParent().getName(), "parent.getParent().getName() must be set");
|
||||
instance.domainHistoryRevisionId = instance.parent.getId();
|
||||
instance.domainRepoId = instance.parent.getParent().getName();
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
@@ -274,7 +291,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "allocation_token_id")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_event_id"))
|
||||
public static class OneTime extends BillingEvent {
|
||||
@WithLongVKey
|
||||
public static class OneTime extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The billable value. */
|
||||
@AttributeOverrides({
|
||||
@@ -309,7 +327,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
* Cancellation}s.
|
||||
*/
|
||||
@Column(name = "cancellation_matching_billing_recurrence_id")
|
||||
VKey<? extends BillingEvent> cancellationMatchingBillingEvent;
|
||||
VKey<Recurring> cancellationMatchingBillingEvent;
|
||||
|
||||
/**
|
||||
* The {@link AllocationToken} used in the creation of this event, or null if one was not used.
|
||||
@@ -391,7 +409,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
}
|
||||
|
||||
public Builder setCancellationMatchingBillingEvent(
|
||||
VKey<? extends BillingEvent> cancellationMatchingBillingEvent) {
|
||||
VKey<Recurring> cancellationMatchingBillingEvent) {
|
||||
getInstance().cancellationMatchingBillingEvent = cancellationMatchingBillingEvent;
|
||||
return this;
|
||||
}
|
||||
@@ -450,7 +468,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "recurrence_time_of_year")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_recurrence_id"))
|
||||
public static class Recurring extends BillingEvent {
|
||||
@WithLongVKey
|
||||
public static class Recurring extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/**
|
||||
* The billing event recurs every year between {@link #eventTime} and this time on the
|
||||
@@ -544,7 +563,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
@javax.persistence.Index(columnList = "billingTime")
|
||||
})
|
||||
@AttributeOverride(name = "id", column = @Column(name = "billing_cancellation_id"))
|
||||
public static class Cancellation extends BillingEvent {
|
||||
@WithLongVKey
|
||||
public static class Cancellation extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The billing time of the charge that is being cancelled. */
|
||||
@Index
|
||||
@@ -664,7 +684,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
/** An event representing a modification of an existing one-time billing event. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class Modification extends BillingEvent {
|
||||
@WithLongVKey
|
||||
public static class Modification extends BillingEvent implements DatastoreAndSqlEntity {
|
||||
|
||||
/** The change in cost that should be applied to the original billing event. */
|
||||
Money cost;
|
||||
|
||||
@@ -14,13 +14,25 @@
|
||||
|
||||
package google.registry.model.contact;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
|
||||
/**
|
||||
* A persisted history entry representing an EPP modification to a contact.
|
||||
@@ -38,21 +50,125 @@ import javax.persistence.Entity;
|
||||
@javax.persistence.Index(columnList = "historyModificationTime")
|
||||
})
|
||||
@EntitySubclass
|
||||
public class ContactHistory extends HistoryEntry {
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(ContactHistoryId.class)
|
||||
public class ContactHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store ContactBase instead of ContactResource so we don't pick up its @Id
|
||||
ContactBase contactBase;
|
||||
@Nullable ContactBase contactBase;
|
||||
|
||||
@Column(nullable = false)
|
||||
VKey<ContactResource> contactRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getContactRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** The state of the {@link ContactBase} object at this point in time. */
|
||||
public ContactBase getContactBase() {
|
||||
return contactBase;
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setContactRepoId(String contactRepoId) {
|
||||
parent = Key.create(ContactResource.class, contactRepoId);
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
public long getId() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* The values of all the fields on the {@link ContactBase} object after the action represented by
|
||||
* this history object was executed.
|
||||
*
|
||||
* <p>Will be absent for objects created prior to the Registry 3.0 SQL migration.
|
||||
*/
|
||||
public Optional<ContactBase> getContactBase() {
|
||||
return Optional.ofNullable(contactBase);
|
||||
}
|
||||
|
||||
/** The key to the {@link ContactResource} this is based off of. */
|
||||
public VKey<ContactResource> getContactRepoId() {
|
||||
return contactRepoId;
|
||||
public VKey<ContactResource> getParentVKey() {
|
||||
return VKey.create(ContactResource.class, getContactRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<ContactHistory> createVKey() {
|
||||
return VKey.create(
|
||||
ContactHistory.class, new ContactHistoryId(getContactRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
// Normally Hibernate would see that the contact fields are all null and would fill contactBase
|
||||
// with a null object. Unfortunately, the updateTimestamp is never null in SQL.
|
||||
if (contactBase != null && contactBase.getContactId() == null) {
|
||||
contactBase = null;
|
||||
}
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link ContactHistory} entity. */
|
||||
static class ContactHistoryId extends ImmutableObject implements Serializable {
|
||||
|
||||
private String contactRepoId;
|
||||
|
||||
private Long id;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private ContactHistoryId() {}
|
||||
|
||||
ContactHistoryId(String contactRepoId, long id) {
|
||||
this.contactRepoId = contactRepoId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contact repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getContactRepoId() {
|
||||
return contactRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the contact repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setContactRepoId(String contactRepoId) {
|
||||
this.contactRepoId = contactRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,18 +189,8 @@ public class ContactHistory extends HistoryEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setContactRepoId(VKey<ContactResource> contactRepoId) {
|
||||
getInstance().contactRepoId = contactRepoId;
|
||||
contactRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().contactRepoId =
|
||||
VKey.create(ContactResource.class, parent.getName(), (Key<ContactResource>) parent);
|
||||
public Builder setContactRepoId(String contactRepoId) {
|
||||
getInstance().parent = Key.create(ContactResource.class, contactRepoId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ public class ContactResource extends ContactBase
|
||||
|
||||
@Override
|
||||
public VKey<ContactResource> createVKey() {
|
||||
// TODO(mmuller): create symmetric keys if we can ever reload both sides.
|
||||
return VKey.create(ContactResource.class, getRepoId(), Key.create(this));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
package google.registry.model.domain;
|
||||
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
@@ -82,17 +82,57 @@ public class DomainBase extends DomainContent
|
||||
return super.nsHosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of {@link GracePeriod} associated with the domain.
|
||||
*
|
||||
* <p>This is the getter method specific for Hibernate to access the field so it is set to
|
||||
* private. The caller can use the public {@link #getGracePeriods()} to get the grace periods.
|
||||
*
|
||||
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
|
||||
* Hibernate would try to set the foreign key to null(through an UPDATE TABLE sql) instead of
|
||||
* deleting the whole entry from the table when the {@link GracePeriod} is removed from the set.
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(
|
||||
cascade = {CascadeType.ALL},
|
||||
fetch = FetchType.EAGER,
|
||||
orphanRemoval = true)
|
||||
@JoinColumn(name = "domainRepoId", referencedColumnName = "repoId")
|
||||
@JoinColumn(
|
||||
name = "domainRepoId",
|
||||
referencedColumnName = "repoId",
|
||||
insertable = false,
|
||||
updatable = false)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private Set<GracePeriod> getInternalGracePeriods() {
|
||||
return gracePeriods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of {@link DelegationSignerData} associated with the domain.
|
||||
*
|
||||
* <p>This is the getter method specific for Hibernate to access the field so it is set to
|
||||
* private. The caller can use the public {@link #getDsData()} to get the DS data.
|
||||
*
|
||||
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
|
||||
* Hibernate would try to set the foreign key to null(through an UPDATE TABLE sql) instead of
|
||||
* deleting the whole entry from the table when the {@link DelegationSignerData} is removed from
|
||||
* the set.
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(
|
||||
cascade = {CascadeType.ALL},
|
||||
fetch = FetchType.EAGER,
|
||||
orphanRemoval = true)
|
||||
@JoinColumn(
|
||||
name = "domainRepoId",
|
||||
referencedColumnName = "repoId",
|
||||
insertable = false,
|
||||
updatable = false)
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private Set<DelegationSignerData> getInternalDelegationSignerData() {
|
||||
return dsData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKey<DomainBase> createVKey() {
|
||||
return VKey.create(DomainBase.class, getRepoId(), Key.create(this));
|
||||
|
||||
@@ -35,11 +35,13 @@ import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||
import static google.registry.util.DomainNameUtils.getTldFromDomainName;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
@@ -49,6 +51,7 @@ import google.registry.flows.ResourceFlowUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
@@ -57,6 +60,7 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -65,7 +69,6 @@ import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
@@ -209,6 +212,15 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "deletion_poll_message_id")
|
||||
VKey<PollMessage.OneTime> deletePollMessage;
|
||||
|
||||
/**
|
||||
* History record for the delete poll message.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Column(name = "deletion_poll_message_history_id")
|
||||
@Ignore
|
||||
Long deletePollMessageHistoryId;
|
||||
|
||||
/**
|
||||
* The recurring billing event associated with this domain's autorenewals.
|
||||
*
|
||||
@@ -220,6 +232,15 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "billing_recurrence_id")
|
||||
VKey<BillingEvent.Recurring> autorenewBillingEvent;
|
||||
|
||||
/**
|
||||
* History record for the autorenew billing event.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Column(name = "billing_recurrence_history_id")
|
||||
@Ignore
|
||||
Long autorenewBillingEventHistoryId;
|
||||
|
||||
/**
|
||||
* The recurring poll message associated with this domain's autorenewals.
|
||||
*
|
||||
@@ -231,6 +252,13 @@ public class DomainContent extends EppResource
|
||||
@Column(name = "autorenew_poll_message_id")
|
||||
VKey<PollMessage.Autorenew> autorenewPollMessage;
|
||||
|
||||
/**
|
||||
* History record for the autorenew poll message.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Ignore Long autorenewPollMessageHistoryId;
|
||||
|
||||
/** The unexpired grace periods for this domain (some of which may not be active yet). */
|
||||
@Transient Set<GracePeriod> gracePeriods;
|
||||
|
||||
@@ -280,16 +308,24 @@ public class DomainContent extends EppResource
|
||||
// object will have a null hashcode so that it can get a recalculated hashcode
|
||||
// when its hashCode() is invoked.
|
||||
// TODO(b/162739503): Remove this after fully migrating to Cloud SQL.
|
||||
if (gracePeriods != null) {
|
||||
gracePeriods =
|
||||
gracePeriods.stream()
|
||||
.map(gracePeriod -> gracePeriod.cloneWithDomainRepoId(getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
gracePeriods =
|
||||
nullToEmptyImmutableCopy(gracePeriods).stream()
|
||||
.map(gracePeriod -> gracePeriod.cloneWithDomainRepoId(getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
|
||||
// Restore history record ids.
|
||||
autorenewPollMessageHistoryId = getHistoryId(autorenewPollMessage);
|
||||
autorenewBillingEventHistoryId = getHistoryId(autorenewBillingEvent);
|
||||
deletePollMessageHistoryId = getHistoryId(deletePollMessage);
|
||||
dsData =
|
||||
nullToEmptyImmutableCopy(dsData).stream()
|
||||
.map(dsData -> dsData.cloneWithDomainRepoId(getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private final void postLoad() {
|
||||
// Reconstitute the contact list.
|
||||
ImmutableSet.Builder<DesignatedContact> contactsBuilder = new ImmutableSet.Builder<>();
|
||||
|
||||
@@ -308,6 +344,27 @@ public class DomainContent extends EppResource
|
||||
}
|
||||
|
||||
allContacts = contactsBuilder.build();
|
||||
|
||||
// Reconstitute the composite ofy keys from the SQL data.
|
||||
Key<DomainBase> myKey = Key.create(DomainBase.class, getRepoId());
|
||||
deletePollMessage = restoreOfyFrom(myKey, deletePollMessage, deletePollMessageHistoryId);
|
||||
autorenewBillingEvent =
|
||||
restoreOfyFrom(myKey, autorenewBillingEvent, autorenewBillingEventHistoryId);
|
||||
autorenewPollMessage =
|
||||
restoreOfyFrom(myKey, autorenewPollMessage, autorenewPollMessageHistoryId);
|
||||
|
||||
if (transferData != null) {
|
||||
transferData.restoreOfyKeys(myKey);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> VKey<T> restoreOfyFrom(Key<DomainBase> domainKey, VKey<T> key, Long historyId) {
|
||||
if (historyId == null) {
|
||||
// This is a legacy key (or a null key, in which case this works too)
|
||||
return VKey.restoreOfyFrom(key, EntityGroupRoot.class, "per-tld");
|
||||
} else {
|
||||
return VKey.restoreOfyFrom(key, domainKey, HistoryEntry.class, historyId);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableSet<String> getSubordinateHosts() {
|
||||
@@ -389,6 +446,12 @@ public class DomainContent extends EppResource
|
||||
this.gracePeriods = gracePeriods;
|
||||
}
|
||||
|
||||
// Hibernate needs this in order to populate dsData but no one else should ever use it
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setInternalDelegationSignerData(Set<DelegationSignerData> dsData) {
|
||||
this.dsData = dsData;
|
||||
}
|
||||
|
||||
public final String getCurrentSponsorClientId() {
|
||||
return getPersistedCurrentSponsorClientId();
|
||||
}
|
||||
@@ -657,13 +720,31 @@ public class DomainContent extends EppResource
|
||||
+ " use DomainBase instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a history id from the given key.
|
||||
*
|
||||
* <p>The key must be a composite key either of the form domain-key/history-key/long-event-key or
|
||||
* EntityGroupRoot/long-event-key (for legacy keys). In the latter case or for a null key returns
|
||||
* a history id of null.
|
||||
*/
|
||||
public static Long getHistoryId(VKey<?> key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
Key<?> parent = key.getOfyKey().getParent();
|
||||
if (parent == null || parent.getKind().equals("EntityGroupRoot")) {
|
||||
return null;
|
||||
}
|
||||
return parent.getId();
|
||||
}
|
||||
|
||||
/** Predicate to determine if a given {@link DesignatedContact} is the registrant. */
|
||||
static final Predicate<DesignatedContact> IS_REGISTRANT =
|
||||
(DesignatedContact contact) -> DesignatedContact.Type.REGISTRANT.equals(contact.type);
|
||||
|
||||
/** An override of {@link EppResource#asBuilder} with tighter typing. */
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
public Builder<? extends DomainContent, ?> asBuilder() {
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
|
||||
@@ -698,7 +779,19 @@ public class DomainContent extends EppResource
|
||||
}
|
||||
checkArgumentNotNull(instance.getRegistrant(), "Missing registrant");
|
||||
instance.tld = getTldFromDomainName(instance.fullyQualifiedDomainName);
|
||||
return super.build();
|
||||
|
||||
T newDomain = super.build();
|
||||
// Hibernate throws exception if gracePeriods or dsData is null because we enabled all
|
||||
// cascadable operations and orphan removal.
|
||||
newDomain.gracePeriods =
|
||||
newDomain.gracePeriods == null ? ImmutableSet.of() : newDomain.gracePeriods;
|
||||
newDomain.dsData =
|
||||
newDomain.dsData == null
|
||||
? ImmutableSet.of()
|
||||
: newDomain.dsData.stream()
|
||||
.map(ds -> ds.cloneWithDomainRepoId(instance.getRepoId()))
|
||||
.collect(toImmutableSet());
|
||||
return newDomain;
|
||||
}
|
||||
|
||||
public B setDomainName(String domainName) {
|
||||
@@ -820,16 +913,19 @@ public class DomainContent extends EppResource
|
||||
|
||||
public B setDeletePollMessage(VKey<PollMessage.OneTime> deletePollMessage) {
|
||||
getInstance().deletePollMessage = deletePollMessage;
|
||||
getInstance().deletePollMessageHistoryId = getHistoryId(deletePollMessage);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAutorenewBillingEvent(VKey<BillingEvent.Recurring> autorenewBillingEvent) {
|
||||
getInstance().autorenewBillingEvent = autorenewBillingEvent;
|
||||
getInstance().autorenewBillingEventHistoryId = getHistoryId(autorenewBillingEvent);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAutorenewPollMessage(VKey<PollMessage.Autorenew> autorenewPollMessage) {
|
||||
getInstance().autorenewPollMessage = autorenewPollMessage;
|
||||
getInstance().autorenewPollMessageHistoryId = getHistoryId(autorenewPollMessage);
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,20 +14,40 @@
|
||||
|
||||
package google.registry.model.domain;
|
||||
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A persisted history entry representing an EPP modification to a domain.
|
||||
@@ -37,44 +57,197 @@ import javax.persistence.JoinTable;
|
||||
* the foreign-keyed fields in that class can refer to this object.
|
||||
*/
|
||||
@Entity
|
||||
@javax.persistence.Table(
|
||||
@Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "creationTime"),
|
||||
@javax.persistence.Index(columnList = "historyRegistrarId"),
|
||||
@javax.persistence.Index(columnList = "historyType"),
|
||||
@javax.persistence.Index(columnList = "historyModificationTime")
|
||||
@Index(columnList = "creationTime"),
|
||||
@Index(columnList = "historyRegistrarId"),
|
||||
@Index(columnList = "historyType"),
|
||||
@Index(columnList = "historyModificationTime")
|
||||
})
|
||||
@EntitySubclass
|
||||
public class DomainHistory extends HistoryEntry {
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(DomainHistoryId.class)
|
||||
public class DomainHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store DomainContent instead of DomainBase so we don't pick up its @Id
|
||||
DomainContent domainContent;
|
||||
@Nullable DomainContent domainContent;
|
||||
|
||||
@Column(nullable = false)
|
||||
VKey<DomainBase> domainRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getDomainRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setDomainRepoId(String domainRepoId) {
|
||||
parent = Key.create(DomainBase.class, domainRepoId);
|
||||
}
|
||||
|
||||
// We could have reused domainContent.nsHosts here, but Hibernate throws a weird exception after
|
||||
// we change to use a composite primary key.
|
||||
// TODO(b/166776754): Investigate if we can reuse domainContent.nsHosts for storing host keys.
|
||||
@Ignore
|
||||
@ElementCollection
|
||||
@JoinTable(name = "DomainHistoryHost")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "host_repo_id")
|
||||
Set<VKey<HostResource>> nsHosts;
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@Access(AccessType.PROPERTY)
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "unit",
|
||||
column = @Column(name = "historyPeriodUnit")),
|
||||
@AttributeOverride(
|
||||
name = "value",
|
||||
column = @Column(name = "historyPeriodValue"))
|
||||
})
|
||||
public Period getPeriod() {
|
||||
return super.getPeriod();
|
||||
}
|
||||
|
||||
/**
|
||||
* For transfers, the id of the other registrar.
|
||||
*
|
||||
* <p>For requests and cancels, the other registrar is the losing party (because the registrar
|
||||
* sending the EPP transfer command is the gaining party). For approves and rejects, the other
|
||||
* registrar is the gaining party.
|
||||
*/
|
||||
@Nullable
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "historyOtherRegistrarId")
|
||||
public String getOtherRegistrarId() {
|
||||
return super.getOtherClientId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logging field for transaction reporting.
|
||||
*
|
||||
* <p>This will be empty for any DomainHistory/HistoryEntry generated before this field was added,
|
||||
* mid-2017, as well as any action that does not generate billable events (e.g. updates).
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(cascade = {CascadeType.ALL})
|
||||
@JoinColumn(name = "historyRevisionId", referencedColumnName = "historyRevisionId")
|
||||
@JoinColumn(name = "domainRepoId", referencedColumnName = "domainRepoId")
|
||||
@Override
|
||||
public Set<DomainTransactionRecord> getDomainTransactionRecords() {
|
||||
return super.getDomainTransactionRecords();
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
public long getId() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
/** Returns keys to the {@link HostResource} that are the nameservers for the domain. */
|
||||
public Set<VKey<HostResource>> getNsHosts() {
|
||||
return domainContent.nsHosts;
|
||||
return nsHosts;
|
||||
}
|
||||
|
||||
/** The state of the {@link DomainContent} object at this point in time. */
|
||||
public DomainContent getDomainContent() {
|
||||
return domainContent;
|
||||
/**
|
||||
* The values of all the fields on the {@link DomainContent} object after the action represented
|
||||
* by this history object was executed.
|
||||
*
|
||||
* <p>Will be absent for objects created prior to the Registry 3.0 SQL migration.
|
||||
*/
|
||||
public Optional<DomainContent> getDomainContent() {
|
||||
return Optional.ofNullable(domainContent);
|
||||
}
|
||||
|
||||
/** The key to the {@link ContactResource} this is based off of. */
|
||||
public VKey<DomainBase> getDomainRepoId() {
|
||||
return domainRepoId;
|
||||
/** The key to the {@link DomainBase} this is based off of. */
|
||||
public VKey<DomainBase> getParentVKey() {
|
||||
return VKey.create(DomainBase.class, getDomainRepoId());
|
||||
}
|
||||
|
||||
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setNsHosts(Set<VKey<HostResource>> nsHosts) {
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<DomainHistory> createVKey() {
|
||||
return VKey.create(
|
||||
DomainHistory.class, new DomainHistoryId(getDomainRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
if (domainContent != null) {
|
||||
domainContent.nsHosts = nsHosts;
|
||||
domainContent.nsHosts = nullToEmptyImmutableCopy(nsHosts);
|
||||
// Normally Hibernate would see that the domain fields are all null and would fill
|
||||
// domainContent with a null object. Unfortunately, the updateTimestamp is never null in SQL.
|
||||
if (domainContent.getDomainName() == null) {
|
||||
domainContent = null;
|
||||
} else {
|
||||
if (domainContent.getRepoId() == null) {
|
||||
domainContent = domainContent.asBuilder().setRepoId(parent.getName()).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link DomainHistory} entity. */
|
||||
static class DomainHistoryId extends ImmutableObject implements Serializable {
|
||||
|
||||
private String domainRepoId;
|
||||
|
||||
private Long id;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private DomainHistoryId() {}
|
||||
|
||||
DomainHistoryId(String domainRepoId, long id) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getDomainRepoId() {
|
||||
return domainRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the domain repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setDomainRepoId(String domainRepoId) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,21 +266,14 @@ public class DomainHistory extends HistoryEntry {
|
||||
|
||||
public Builder setDomainContent(DomainContent domainContent) {
|
||||
getInstance().domainContent = domainContent;
|
||||
if (domainContent != null) {
|
||||
getInstance().nsHosts = nullToEmptyImmutableCopy(domainContent.nsHosts);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDomainRepoId(VKey<DomainBase> domainRepoId) {
|
||||
getInstance().domainRepoId = domainRepoId;
|
||||
domainRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().domainRepoId =
|
||||
VKey.create(DomainBase.class, parent.getName(), (Key<DomainBase>) parent);
|
||||
public Builder setDomainRepoId(String domainRepoId) {
|
||||
getInstance().parent = Key.create(DomainBase.class, domainRepoId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
@@ -37,7 +38,7 @@ import org.joda.time.DateTime;
|
||||
@Embed
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||
public class GracePeriod extends GracePeriodBase {
|
||||
public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntity {
|
||||
|
||||
private static GracePeriod createInternal(
|
||||
GracePeriodStatus type,
|
||||
|
||||
@@ -31,9 +31,9 @@ public class Period extends ImmutableObject {
|
||||
@XmlAttribute
|
||||
Unit unit;
|
||||
|
||||
@XmlValue
|
||||
Integer value;
|
||||
@XmlValue Integer value;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
public Unit getUnit() {
|
||||
return unit;
|
||||
}
|
||||
@@ -42,6 +42,18 @@ public class Period extends ImmutableObject {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use {@link #create(int, Unit)} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setUnit(Unit unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use {@link #create(int, Unit)} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setValue(Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** The unit enum. */
|
||||
public enum Unit {
|
||||
@XmlEnumValue("y")
|
||||
|
||||
@@ -14,10 +14,22 @@
|
||||
|
||||
package google.registry.model.domain.secdns;
|
||||
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData.DelegationSignerDataId;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
@@ -30,19 +42,26 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
*/
|
||||
@Embed
|
||||
@XmlType(name = "dsData")
|
||||
@javax.persistence.Entity
|
||||
public class DelegationSignerData extends ImmutableObject {
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "domainRepoId"))
|
||||
@IdClass(DelegationSignerDataId.class)
|
||||
public class DelegationSignerData extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
|
||||
private DelegationSignerData() {}
|
||||
|
||||
@Ignore @XmlTransient @javax.persistence.Id String domainRepoId;
|
||||
|
||||
/** The identifier for this particular key in the domain. */
|
||||
@javax.persistence.Id int keyTag;
|
||||
@javax.persistence.Id
|
||||
@Column(nullable = false)
|
||||
int keyTag;
|
||||
|
||||
/**
|
||||
* The algorithm used by this key.
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.1">RFC 4034 Appendix A.1</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@XmlElement(name = "alg")
|
||||
int algorithm;
|
||||
|
||||
@@ -51,6 +70,7 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#appendix-A.2">RFC 4034 Appendix A.2</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
int digestType;
|
||||
|
||||
/**
|
||||
@@ -58,6 +78,7 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/rfc4034#section-5.1.4">RFC 4034 Section 5.1.4</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@XmlJavaTypeAdapter(HexBinaryAdapter.class)
|
||||
byte[] digest;
|
||||
|
||||
@@ -81,16 +102,34 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
return digest == null ? "" : DatatypeConverter.printHexBinary(digest);
|
||||
}
|
||||
|
||||
public DelegationSignerData cloneWithDomainRepoId(String domainRepoId) {
|
||||
DelegationSignerData clone = clone(this);
|
||||
clone.domainRepoId = checkArgumentNotNull(domainRepoId);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public DelegationSignerData cloneWithoutDomainRepoId() {
|
||||
DelegationSignerData clone = clone(this);
|
||||
clone.domainRepoId = null;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||
int keyTag, int algorithm, int digestType, byte[] digest, String domainRepoId) {
|
||||
DelegationSignerData instance = new DelegationSignerData();
|
||||
instance.keyTag = keyTag;
|
||||
instance.algorithm = algorithm;
|
||||
instance.digestType = digestType;
|
||||
instance.digest = digest;
|
||||
instance.domainRepoId = domainRepoId;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||
return create(keyTag, algorithm, digestType, digest, null);
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, String digestAsHex) {
|
||||
return create(keyTag, algorithm, digestType, DatatypeConverter.parseHexBinary(digestAsHex));
|
||||
@@ -106,4 +145,20 @@ public class DelegationSignerData extends ImmutableObject {
|
||||
"%d %d %d %s",
|
||||
this.keyTag, this.algorithm, this.digestType, DatatypeConverter.printHexBinary(digest));
|
||||
}
|
||||
|
||||
static class DelegationSignerDataId extends ImmutableObject implements Serializable {
|
||||
String domainRepoId;
|
||||
int keyTag;
|
||||
|
||||
private DelegationSignerDataId() {}
|
||||
|
||||
private DelegationSignerDataId(String domainRepoId, int keyTag) {
|
||||
this.domainRepoId = domainRepoId;
|
||||
this.keyTag = keyTag;
|
||||
}
|
||||
|
||||
public static DelegationSignerDataId create(String domainRepoId, int keyTag) {
|
||||
return new DelegationSignerDataId(checkArgumentNotNull(domainRepoId), keyTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ import static com.google.common.base.Strings.nullToEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainContent;
|
||||
import google.registry.model.host.HostBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||
@@ -128,9 +130,15 @@ public enum StatusValue implements EppEnum {
|
||||
|
||||
/** Enum to help clearly list which resource types a status value is allowed to be present on. */
|
||||
private enum AllowedOn {
|
||||
ALL(ContactResource.class, DomainBase.class, HostBase.class, HostResource.class),
|
||||
ALL(
|
||||
ContactBase.class,
|
||||
ContactResource.class,
|
||||
DomainContent.class,
|
||||
DomainBase.class,
|
||||
HostBase.class,
|
||||
HostResource.class),
|
||||
NONE,
|
||||
DOMAINS(DomainBase.class);
|
||||
DOMAINS(DomainContent.class, DomainBase.class);
|
||||
|
||||
private final ImmutableSet<Class<? extends EppResource>> classes;
|
||||
|
||||
|
||||
@@ -14,13 +14,25 @@
|
||||
|
||||
package google.registry.model.host;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.host.HostHistory.HostHistoryId;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
|
||||
/**
|
||||
* A persisted history entry representing an EPP modification to a host.
|
||||
@@ -39,22 +51,125 @@ import javax.persistence.Entity;
|
||||
@javax.persistence.Index(columnList = "historyModificationTime")
|
||||
})
|
||||
@EntitySubclass
|
||||
public class HostHistory extends HistoryEntry {
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(HostHistoryId.class)
|
||||
public class HostHistory extends HistoryEntry implements SqlEntity {
|
||||
|
||||
// Store HostBase instead of HostResource so we don't pick up its @Id
|
||||
HostBase hostBase;
|
||||
@Nullable HostBase hostBase;
|
||||
|
||||
@Column(nullable = false)
|
||||
VKey<HostResource> hostRepoId;
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getHostRepoId() {
|
||||
return parent.getName();
|
||||
}
|
||||
|
||||
/** The state of the {@link HostBase} object at this point in time. */
|
||||
public HostBase getHostBase() {
|
||||
return hostBase;
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setHostRepoId(String hostRepoId) {
|
||||
parent = Key.create(HostResource.class, hostRepoId);
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "historyRevisionId")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@Override
|
||||
public long getId() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* The values of all the fields on the {@link HostBase} object after the action represented by
|
||||
* this history object was executed.
|
||||
*
|
||||
* <p>Will be absent for objects created prior to the Registry 3.0 SQL migration.
|
||||
*/
|
||||
public Optional<HostBase> getHostBase() {
|
||||
return Optional.ofNullable(hostBase);
|
||||
}
|
||||
|
||||
/** The key to the {@link google.registry.model.host.HostResource} this is based off of. */
|
||||
public VKey<HostResource> getHostRepoId() {
|
||||
return hostRepoId;
|
||||
public VKey<HostResource> getParentVKey() {
|
||||
return VKey.create(HostResource.class, getHostRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
public VKey<HostHistory> createVKey() {
|
||||
return VKey.create(
|
||||
HostHistory.class, new HostHistoryId(getHostRepoId(), getId()), Key.create(this));
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
// Normally Hibernate would see that the host fields are all null and would fill hostBase
|
||||
// with a null object. Unfortunately, the updateTimestamp is never null in SQL.
|
||||
if (hostBase != null && hostBase.getHostName() == null) {
|
||||
hostBase = null;
|
||||
}
|
||||
}
|
||||
|
||||
// In Datastore, save as a HistoryEntry object regardless of this object's type
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(asHistoryEntry());
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link HostHistory} entity. */
|
||||
static class HostHistoryId extends ImmutableObject implements Serializable {
|
||||
|
||||
private String hostRepoId;
|
||||
|
||||
private Long id;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private HostHistoryId() {}
|
||||
|
||||
HostHistoryId(String hostRepoId, long id) {
|
||||
this.hostRepoId = hostRepoId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the host repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private String getHostRepoId() {
|
||||
return hostRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host repository id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setHostRepoId(String hostRepoId) {
|
||||
this.hostRepoId = hostRepoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history revision id.
|
||||
*
|
||||
* <p>This method is private because it is only used by Hibernate and should not be used
|
||||
* externally to keep immutability.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,18 +190,8 @@ public class HostHistory extends HistoryEntry {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHostRepoId(VKey<HostResource> hostRepoId) {
|
||||
getInstance().hostRepoId = hostRepoId;
|
||||
hostRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||
return this;
|
||||
}
|
||||
|
||||
// We can remove this once all HistoryEntries are converted to History objects
|
||||
@Override
|
||||
public Builder setParent(Key<? extends EppResource> parent) {
|
||||
super.setParent(parent);
|
||||
getInstance().hostRepoId =
|
||||
VKey.create(HostResource.class, parent.getName(), (Key<HostResource>) parent);
|
||||
public Builder setHostRepoId(String hostRepoId) {
|
||||
getInstance().parent = Key.create(HostResource.class, hostRepoId);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import javax.persistence.AccessType;
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@javax.persistence.Entity(name = "Host")
|
||||
@ExternalMessagingName("host")
|
||||
@WithStringVKey
|
||||
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property)
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.model.index;
|
||||
import static google.registry.util.TypeUtils.instantiate;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
@@ -25,11 +26,13 @@ import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
|
||||
/** An index that allows for quick enumeration of all EppResource entities (e.g. via map reduce). */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public class EppResourceIndex extends BackupGroupRoot {
|
||||
public class EppResourceIndex extends BackupGroupRoot implements DatastoreEntity {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
@@ -74,4 +77,9 @@ public class EppResourceIndex extends BackupGroupRoot {
|
||||
public static <T extends EppResource> EppResourceIndex create(Key<T> resourceKey) {
|
||||
return create(EppResourceIndexBucket.getBucketKey(resourceKey), resourceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not relevant in SQL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,23 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
|
||||
/** A virtual entity to represent buckets to which EppResourceIndex objects are randomly added. */
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
public class EppResourceIndexBucket extends ImmutableObject {
|
||||
public class EppResourceIndexBucket extends ImmutableObject implements DatastoreEntity {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Id
|
||||
private long bucketId;
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not relevant in SQL
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterministic function that returns a bucket id based on the resource's roid.
|
||||
* NB: At the moment, nothing depends on this being deterministic, so we have the ability to
|
||||
|
||||
@@ -20,7 +20,6 @@ import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntri
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.TypeUtils.instantiate;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
@@ -43,6 +42,8 @@ import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -61,28 +62,44 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
/** The {@link ForeignKeyIndex} type for {@link ContactResource} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyContactIndex extends ForeignKeyIndex<ContactResource> {}
|
||||
public static class ForeignKeyContactIndex extends ForeignKeyIndex<ContactResource>
|
||||
implements DatastoreEntity {
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not relevant in SQL
|
||||
}
|
||||
}
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link DomainBase} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyDomainIndex extends ForeignKeyIndex<DomainBase> {}
|
||||
public static class ForeignKeyDomainIndex extends ForeignKeyIndex<DomainBase>
|
||||
implements DatastoreEntity {
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not relevant in SQL
|
||||
}
|
||||
}
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link HostResource} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyHostIndex extends ForeignKeyIndex<HostResource> {}
|
||||
public static class ForeignKeyHostIndex extends ForeignKeyIndex<HostResource>
|
||||
implements DatastoreEntity {
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not relevant in SQL
|
||||
}
|
||||
}
|
||||
|
||||
static final ImmutableMap<
|
||||
Class<? extends EppResource>, Class<? extends ForeignKeyIndex<?>>>
|
||||
static final ImmutableMap<Class<? extends EppResource>, Class<? extends ForeignKeyIndex<?>>>
|
||||
RESOURCE_CLASS_TO_FKI_CLASS =
|
||||
ImmutableMap.of(
|
||||
ContactResource.class, ForeignKeyContactIndex.class,
|
||||
DomainBase.class, ForeignKeyDomainIndex.class,
|
||||
HostResource.class, ForeignKeyHostIndex.class);
|
||||
|
||||
@Id
|
||||
String foreignKey;
|
||||
@Id String foreignKey;
|
||||
|
||||
/**
|
||||
* The deletion time of this {@link ForeignKeyIndex}.
|
||||
@@ -90,8 +107,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
* <p>This will generally be equal to the deletion time of {@link #topReference}. However, in the
|
||||
* case of a {@link HostResource} that was renamed, this field will hold the time of the rename.
|
||||
*/
|
||||
@Index
|
||||
DateTime deletionTime;
|
||||
@Index DateTime deletionTime;
|
||||
|
||||
/**
|
||||
* The referenced resource.
|
||||
@@ -227,7 +243,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
private static LoadingCache<Key<ForeignKeyIndex<?>>, Optional<ForeignKeyIndex<?>>>
|
||||
createForeignKeyIndexesCache(Duration expiry) {
|
||||
return CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(expiry.getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(java.time.Duration.ofMillis(expiry.getMillis()))
|
||||
.maximumSize(getEppResourceMaxCachedEntries())
|
||||
.build(CACHE_LOADER);
|
||||
}
|
||||
|
||||
@@ -101,22 +101,22 @@ public class DatastoreTransactionManager implements TransactionManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveNew(Object entity) {
|
||||
public void insert(Object entity) {
|
||||
saveEntity(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllNew(ImmutableCollection<?> entities) {
|
||||
public void insertAll(ImmutableCollection<?> entities) {
|
||||
getOfy().save().entities(entities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveNewOrUpdate(Object entity) {
|
||||
public void put(Object entity) {
|
||||
saveEntity(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveNewOrUpdateAll(ImmutableCollection<?> entities) {
|
||||
public void putAll(ImmutableCollection<?> entities) {
|
||||
getOfy().save().entities(entities);
|
||||
}
|
||||
|
||||
@@ -131,12 +131,12 @@ public class DatastoreTransactionManager implements TransactionManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkExists(Object entity) {
|
||||
public boolean exists(Object entity) {
|
||||
return getOfy().load().key(Key.create(entity)).now() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean checkExists(VKey<T> key) {
|
||||
public <T> boolean exists(VKey<T> key) {
|
||||
return loadNullable(key) != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,18 @@ import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainRenewData;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseData;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.HostPendingActionNotificationResponse;
|
||||
@@ -45,6 +49,7 @@ import google.registry.model.transfer.TransferResponse.ContactTransferResponse;
|
||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithLongVKey;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.AttributeOverride;
|
||||
@@ -53,10 +58,9 @@ import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -92,12 +96,11 @@ import org.joda.time.DateTime;
|
||||
@javax.persistence.Index(columnList = "eventTime")
|
||||
})
|
||||
public abstract class PollMessage extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity {
|
||||
implements Buildable, DatastoreAndSqlEntity, TransferServerApproveEntity {
|
||||
|
||||
/** Entity id. */
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "poll_message_id")
|
||||
Long id;
|
||||
|
||||
@@ -123,11 +126,11 @@ public abstract class PollMessage extends ImmutableObject
|
||||
|
||||
@Ignore String hostRepoId;
|
||||
|
||||
@Ignore Long domainRevisionId;
|
||||
@Ignore Long domainHistoryRevisionId;
|
||||
|
||||
@Ignore Long contactRevisionId;
|
||||
@Ignore Long contactHistoryRevisionId;
|
||||
|
||||
@Ignore Long hostRevisionId;
|
||||
@Ignore Long hostHistoryRevisionId;
|
||||
|
||||
public Key<HistoryEntry> getParentKey() {
|
||||
return parent;
|
||||
@@ -151,6 +154,34 @@ public abstract class PollMessage extends ImmutableObject
|
||||
|
||||
public abstract ImmutableList<ResponseData> getResponseData();
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
if (domainRepoId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(DomainBase.class, domainRepoId),
|
||||
HistoryEntry.class,
|
||||
domainHistoryRevisionId);
|
||||
} else if (contactRepoId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(ContactResource.class, contactRepoId),
|
||||
HistoryEntry.class,
|
||||
contactHistoryRevisionId);
|
||||
} else if (hostHistoryRevisionId != null) {
|
||||
parent =
|
||||
Key.create(
|
||||
Key.create(HostResource.class, hostRepoId),
|
||||
HistoryEntry.class,
|
||||
hostHistoryRevisionId);
|
||||
}
|
||||
}
|
||||
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
setSqlForeignKeys(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends PollMessage> createVKey();
|
||||
|
||||
@@ -216,10 +247,30 @@ public abstract class PollMessage extends ImmutableObject
|
||||
checkArgumentNotNull(instance.clientId, "clientId must be specified");
|
||||
checkArgumentNotNull(instance.eventTime, "eventTime must be specified");
|
||||
checkArgumentNotNull(instance.parent, "parent must be specified");
|
||||
checkArgumentNotNull(instance.parent.getParent(), "parent.getParent() must be specified");
|
||||
setSqlForeignKeys(instance);
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static void setSqlForeignKeys(PollMessage pollMessage) {
|
||||
String grandparentKind = pollMessage.parent.getParent().getKind();
|
||||
String repoId = pollMessage.parent.getParent().getName();
|
||||
long historyRevisionId = pollMessage.parent.getId();
|
||||
if (Key.getKind(DomainBase.class).equals(grandparentKind)) {
|
||||
pollMessage.domainRepoId = repoId;
|
||||
pollMessage.domainHistoryRevisionId = historyRevisionId;
|
||||
} else if (Key.getKind(ContactResource.class).equals(grandparentKind)) {
|
||||
pollMessage.contactRepoId = repoId;
|
||||
pollMessage.contactHistoryRevisionId = historyRevisionId;
|
||||
} else if (Key.getKind(HostResource.class).equals(grandparentKind)) {
|
||||
pollMessage.hostRepoId = repoId;
|
||||
pollMessage.hostHistoryRevisionId = historyRevisionId;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown grandparent kind: " + grandparentKind);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A one-time poll message.
|
||||
*
|
||||
|
||||
@@ -15,17 +15,32 @@
|
||||
package google.registry.model.rde;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.common.base.Verify.verifyNotNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.rde.RdeNamingUtils.makePartialName;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.rde.RdeRevision.RdeRevisionId;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.converter.LocalDateConverter;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Datastore entity for tracking RDE revisions.
|
||||
@@ -35,32 +50,67 @@ import org.joda.time.DateTime;
|
||||
* flag is included in the generated XML.
|
||||
*/
|
||||
@Entity
|
||||
public final class RdeRevision extends ImmutableObject {
|
||||
@javax.persistence.Entity
|
||||
@IdClass(RdeRevisionId.class)
|
||||
public final class RdeRevision extends BackupGroupRoot implements DatastoreEntity, SqlEntity {
|
||||
|
||||
/** String triplet of tld, date, and mode, e.g. {@code soy_2015-09-01_full}. */
|
||||
@Id
|
||||
String id;
|
||||
@Id @Transient String id;
|
||||
|
||||
@javax.persistence.Id @Ignore String tld;
|
||||
|
||||
@javax.persistence.Id @Ignore LocalDate date;
|
||||
|
||||
@javax.persistence.Id @Ignore RdeMode mode;
|
||||
|
||||
/**
|
||||
* Number of last revision successfully staged to GCS.
|
||||
*
|
||||
* <p>This values begins at zero upon object creation and thenceforth incremented transactionally.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
int revision;
|
||||
|
||||
/** Hibernate requires an empty constructor. */
|
||||
private RdeRevision() {}
|
||||
|
||||
public static RdeRevision create(
|
||||
String id, String tld, LocalDate date, RdeMode mode, int revision) {
|
||||
RdeRevision instance = new RdeRevision();
|
||||
instance.id = id;
|
||||
instance.tld = tld;
|
||||
instance.date = date;
|
||||
instance.mode = mode;
|
||||
instance.revision = revision;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public int getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // we don't care about RdeRevision history
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<DatastoreEntity> toDatastoreEntities() {
|
||||
return ImmutableList.of(); // we don't care about RdeRevision history
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next revision ID to use when staging a new deposit file for the given triplet.
|
||||
*
|
||||
* @return {@code 0} for first deposit generation and {@code >0} for resends
|
||||
*/
|
||||
public static int getNextRevision(String tld, DateTime date, RdeMode mode) {
|
||||
RdeRevision object =
|
||||
ofy().load().type(RdeRevision.class).id(makePartialName(tld, date, mode)).now();
|
||||
return object == null ? 0 : object.revision + 1;
|
||||
String id = makePartialName(tld, date, mode);
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, id);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().maybeLoad(VKey.create(RdeRevision.class, sqlKey, ofyKey));
|
||||
return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,17 +126,56 @@ public final class RdeRevision extends ImmutableObject {
|
||||
checkArgument(revision >= 0, "Negative revision: %s", revision);
|
||||
String triplet = makePartialName(tld, date, mode);
|
||||
tm().assertInTransaction();
|
||||
RdeRevision object = ofy().load().type(RdeRevision.class).id(triplet).now();
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, triplet);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().maybeLoad(VKey.create(RdeRevision.class, sqlKey, ofyKey));
|
||||
if (revision == 0) {
|
||||
verify(object == null, "RdeRevision object already created: %s", object);
|
||||
revisionOptional.ifPresent(
|
||||
rdeRevision -> {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"RdeRevision object already created and revision 0 specified: %s",
|
||||
rdeRevision));
|
||||
});
|
||||
} else {
|
||||
verifyNotNull(object, "RDE revision object missing for %s?! revision=%s", triplet, revision);
|
||||
verify(object.revision == revision - 1,
|
||||
"RDE revision object should be at %s but was: %s", revision - 1, object);
|
||||
checkArgument(
|
||||
revisionOptional.isPresent(),
|
||||
"Couldn't find existing RDE revision %s when trying to save new revision %s",
|
||||
triplet,
|
||||
revision);
|
||||
checkArgument(
|
||||
revisionOptional.get().revision == revision - 1,
|
||||
"RDE revision object should be at revision %s but was: %s",
|
||||
revision - 1,
|
||||
revisionOptional.get());
|
||||
}
|
||||
RdeRevision object = RdeRevision.create(triplet, tld, date.toLocalDate(), mode, revision);
|
||||
tm().put(object);
|
||||
}
|
||||
|
||||
/** Class to represent the composite primary key of {@link RdeRevision} entity. */
|
||||
static class RdeRevisionId extends ImmutableObject implements Serializable {
|
||||
|
||||
String tld;
|
||||
|
||||
// Auto-conversion doesn't work for ID classes, we must specify @Column and @Convert
|
||||
@Column(columnDefinition = "date")
|
||||
@Convert(converter = LocalDateConverter.class)
|
||||
LocalDate date;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
RdeMode mode;
|
||||
|
||||
/** Hibernate requires this default constructor. */
|
||||
private RdeRevisionId() {}
|
||||
|
||||
static RdeRevisionId create(String tld, LocalDate date, RdeMode mode) {
|
||||
RdeRevisionId instance = new RdeRevisionId();
|
||||
instance.tld = tld;
|
||||
instance.date = date;
|
||||
instance.mode = mode;
|
||||
return instance;
|
||||
}
|
||||
object = new RdeRevision();
|
||||
object.id = triplet;
|
||||
object.revision = revision;
|
||||
ofy().save().entity(object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
@@ -62,6 +61,7 @@ import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||
import google.registry.model.domain.fee.Fee;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -70,6 +70,13 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -78,21 +85,31 @@ import org.joda.time.Duration;
|
||||
/** Persisted per-TLD configuration data. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public class Registry extends ImmutableObject implements Buildable {
|
||||
@javax.persistence.Entity(name = "Tld")
|
||||
public class Registry extends ImmutableObject implements Buildable, DatastoreAndSqlEntity {
|
||||
|
||||
@Parent Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
|
||||
/**
|
||||
* The canonical string representation of the TLD associated with this {@link Registry}, which is
|
||||
* the standard ASCII for regular TLDs and punycoded ASCII for IDN TLDs.
|
||||
*/
|
||||
@Id String tldStrId;
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@Column(name = "tld_name", nullable = false)
|
||||
String tldStrId;
|
||||
|
||||
/**
|
||||
* A duplicate of {@link #tldStrId}, to simplify BigQuery reporting since the id field becomes
|
||||
* {@code __key__.name} rather than being exported as a named field.
|
||||
*/
|
||||
String tldStr;
|
||||
@Transient String tldStr;
|
||||
|
||||
/** Sets the Datastore specific field, tldStr, when the entity is loaded from Cloud SQL */
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
tldStr = tldStrId;
|
||||
}
|
||||
|
||||
/** The suffix that identifies roids as belonging to this specific tld, e.g. -HOW for .how. */
|
||||
String roidSuffix;
|
||||
@@ -116,6 +133,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8);
|
||||
public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100);
|
||||
public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20);
|
||||
public static final Money DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST = Money.of(USD, 0);
|
||||
|
||||
/** The type of TLD, which determines things like backups and escrow policy. */
|
||||
public enum TldType {
|
||||
@@ -241,7 +259,8 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
/** A cache that loads the {@link Registry} for a given tld. */
|
||||
private static final LoadingCache<String, Optional<Registry>> CACHE =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(getSingletonCacheRefreshDuration().getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(
|
||||
java.time.Duration.ofMillis(getSingletonCacheRefreshDuration().getMillis()))
|
||||
.build(
|
||||
new CacheLoader<String, Optional<Registry>>() {
|
||||
@Override
|
||||
@@ -289,6 +308,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
* <p>All entries of this list must be valid keys for the map of {@code DnsWriter}s injected by
|
||||
* <code>@Inject Map<String, DnsWriter></code>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
Set<String> dnsWriters;
|
||||
|
||||
/**
|
||||
@@ -312,6 +332,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
* <p>Failure to do so can result in parallel writes to the {@link
|
||||
* google.registry.dns.writer.DnsWriter}, which may be dangerous depending on your implementation.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
int numDnsPublishLocks;
|
||||
|
||||
/** Updates an unset numDnsPublishLocks (0) to the standard default of 1. */
|
||||
@@ -327,6 +348,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
* <p>This will be equal to {@link #tldStr} for ASCII TLDs, but will be non-ASCII for IDN TLDs. We
|
||||
* store this in a field so that it will be retained upon import into BigQuery.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
String tldUnicode;
|
||||
|
||||
/**
|
||||
@@ -334,31 +356,37 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
*
|
||||
* <p>This is optional; if not configured, then information won't be exported for this TLD.
|
||||
*/
|
||||
String driveFolderId;
|
||||
@Nullable String driveFolderId;
|
||||
|
||||
/** The type of the TLD, whether it's real or for testing. */
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
TldType tldType = TldType.REAL;
|
||||
|
||||
/**
|
||||
* Whether to disable invoicing for a {@link TldType#REAL} TLD.
|
||||
* Whether to enable invoicing for this TLD.
|
||||
*
|
||||
* <p>Note that invoicing is always disabled for {@link TldType#TEST} TLDs. Setting this field has
|
||||
* no effect for {@link TldType#TEST} TLDs.
|
||||
* <p>Note that this boolean is the sole determiner on whether invoices should be generated for a
|
||||
* TLD. This applies to {@link TldType#TEST} TLDs as well.
|
||||
*/
|
||||
boolean disableInvoicing = false;
|
||||
@Column(nullable = false)
|
||||
boolean invoicingEnabled = false;
|
||||
|
||||
/**
|
||||
* A property that transitions to different TldStates at different times. Stored as a list of
|
||||
* TldStateTransition embedded objects using the @Mapify annotation.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@Mapify(TimedTransitionProperty.TimeMapper.class)
|
||||
TimedTransitionProperty<TldState, TldStateTransition> tldStateTransitions =
|
||||
TimedTransitionProperty.forMapify(DEFAULT_TLD_STATE, TldStateTransition.class);
|
||||
|
||||
/** An automatically managed creation timestamp. */
|
||||
@Column(nullable = false)
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** The set of reserved lists that are applicable to this registry. */
|
||||
@Column(name = "reserved_list_names", nullable = false)
|
||||
Set<Key<ReservedList>> reservedLists;
|
||||
|
||||
/** Retrieves an ImmutableSet of all ReservedLists associated with this tld. */
|
||||
@@ -367,12 +395,15 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
}
|
||||
|
||||
/** The static {@link PremiumList} for this TLD, if there is one. */
|
||||
@Column(name = "premium_list_name", nullable = true)
|
||||
Key<PremiumList> premiumList;
|
||||
|
||||
/** Should RDE upload a nightly escrow deposit for this TLD? */
|
||||
@Column(nullable = false)
|
||||
boolean escrowEnabled = DEFAULT_ESCROW_ENABLED;
|
||||
|
||||
/** Whether the pull queue that writes to authoritative DNS is paused for this TLD. */
|
||||
@Column(nullable = false)
|
||||
boolean dnsPaused = DEFAULT_DNS_PAUSED;
|
||||
|
||||
/**
|
||||
@@ -381,41 +412,85 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
* <p>Domain deletes are free and effective immediately so long as they take place within this
|
||||
* amount of time following creation.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
Duration addGracePeriodLength = DEFAULT_ADD_GRACE_PERIOD;
|
||||
|
||||
/** The length of the anchor tenant add grace period for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration anchorTenantAddGracePeriodLength = DEFAULT_ANCHOR_TENANT_ADD_GRACE_PERIOD;
|
||||
|
||||
/** The length of the auto renew grace period for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration autoRenewGracePeriodLength = DEFAULT_AUTO_RENEW_GRACE_PERIOD;
|
||||
|
||||
/** The length of the redemption grace period for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration redemptionGracePeriodLength = DEFAULT_REDEMPTION_GRACE_PERIOD;
|
||||
|
||||
/** The length of the renew grace period for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration renewGracePeriodLength = DEFAULT_RENEW_GRACE_PERIOD;
|
||||
|
||||
/** The length of the transfer grace period for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration transferGracePeriodLength = DEFAULT_TRANSFER_GRACE_PERIOD;
|
||||
|
||||
/** The length of time before a transfer is automatically approved for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration automaticTransferLength = DEFAULT_AUTOMATIC_TRANSFER_LENGTH;
|
||||
|
||||
/** The length of time a domain spends in the non-redeemable pending delete phase for this TLD. */
|
||||
@Column(nullable = false)
|
||||
Duration pendingDeleteLength = DEFAULT_PENDING_DELETE_LENGTH;
|
||||
|
||||
/** The currency unit for all costs associated with this TLD. */
|
||||
@Column(nullable = false)
|
||||
CurrencyUnit currency = DEFAULT_CURRENCY;
|
||||
|
||||
/** The per-year billing cost for registering a new domain name. */
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "money.amount",
|
||||
column = @Column(name = "create_billing_cost_amount")),
|
||||
@AttributeOverride(
|
||||
name = "money.currency",
|
||||
column = @Column(name = "create_billing_cost_currency"))
|
||||
})
|
||||
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
|
||||
|
||||
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "money.amount",
|
||||
column = @Column(name = "restore_billing_cost_amount")),
|
||||
@AttributeOverride(
|
||||
name = "money.currency",
|
||||
column = @Column(name = "restore_billing_cost_currency"))
|
||||
})
|
||||
Money restoreBillingCost = DEFAULT_RESTORE_BILLING_COST;
|
||||
|
||||
/** The one-time billing cost for changing the server status (i.e. lock). */
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "money.amount",
|
||||
column = @Column(name = "server_status_change_billing_cost_amount")),
|
||||
@AttributeOverride(
|
||||
name = "money.currency",
|
||||
column = @Column(name = "server_status_change_billing_cost_currency"))
|
||||
})
|
||||
Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST;
|
||||
|
||||
/** The one-time billing cost for a registry lock/unlock action initiated by a registrar. */
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
name = "money.amount",
|
||||
column = @Column(name = "registry_lock_or_unlock_cost_amount")),
|
||||
@AttributeOverride(
|
||||
name = "money.currency",
|
||||
column = @Column(name = "registry_lock_or_unlock_cost_currency"))
|
||||
})
|
||||
Money registryLockOrUnlockBillingCost = DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST;
|
||||
|
||||
/**
|
||||
* A property that transitions to different renew billing costs at different times. Stored as a
|
||||
* list of BillingCostTransition embedded objects using the @Mapify annotation.
|
||||
@@ -424,11 +499,13 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
* name. This cost is also used to compute costs for transfers, since each transfer includes a
|
||||
* renewal to ensure transfers have a cost.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
@Mapify(TimedTransitionProperty.TimeMapper.class)
|
||||
TimedTransitionProperty<Money, BillingCostTransition> renewBillingCostTransitions =
|
||||
TimedTransitionProperty.forMapify(DEFAULT_RENEW_BILLING_COST, BillingCostTransition.class);
|
||||
|
||||
/** A property that tracks the EAP fee schedule (if any) for the TLD. */
|
||||
@Column(nullable = false)
|
||||
@Mapify(TimedTransitionProperty.TimeMapper.class)
|
||||
TimedTransitionProperty<Money, BillingCostTransition> eapFeeSchedule =
|
||||
TimedTransitionProperty.forMapify(DEFAULT_EAP_BILLING_COST, BillingCostTransition.class);
|
||||
@@ -437,13 +514,14 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
String lordnUsername;
|
||||
|
||||
/** The end of the claims period (at or after this time, claims no longer applies). */
|
||||
@Column(nullable = false)
|
||||
DateTime claimsPeriodEnd = END_OF_TIME;
|
||||
|
||||
/** An allow list of clients allowed to be used on domains on this TLD (ignored if empty). */
|
||||
Set<String> allowedRegistrantContactIds;
|
||||
@Nullable Set<String> allowedRegistrantContactIds;
|
||||
|
||||
/** An allow list of hosts allowed to be used on domains on this TLD (ignored if empty). */
|
||||
Set<String> allowedFullyQualifiedHostNames;
|
||||
@Nullable Set<String> allowedFullyQualifiedHostNames;
|
||||
|
||||
public String getTldStr() {
|
||||
return tldStr;
|
||||
@@ -566,6 +644,11 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
return serverStatusChangeBillingCost;
|
||||
}
|
||||
|
||||
/** Returns the cost of a registry lock/unlock. */
|
||||
public Money getRegistryLockOrUnlockBillingCost() {
|
||||
return registryLockOrUnlockBillingCost;
|
||||
}
|
||||
|
||||
public ImmutableSortedMap<DateTime, TldState> getTldStateTransitions() {
|
||||
return tldStateTransitions.toValueMap();
|
||||
}
|
||||
@@ -646,8 +729,8 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDisableInvoicing(boolean disableInvoicing) {
|
||||
getInstance().disableInvoicing = disableInvoicing;
|
||||
public Builder setInvoicingEnabled(boolean invoicingEnabled) {
|
||||
getInstance().invoicingEnabled = invoicingEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -867,6 +950,12 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockOrUnlockBillingCost(Money amount) {
|
||||
checkArgument(amount.isPositiveOrZero(), "Registry lock/unlock cost cannot be negative");
|
||||
getInstance().registryLockOrUnlockBillingCost = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLordnUsername(String username) {
|
||||
getInstance().lordnUsername = username;
|
||||
return this;
|
||||
@@ -918,6 +1007,9 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||
checkArgument(
|
||||
instance.getServerStatusChangeCost().getCurrencyUnit().equals(instance.currency),
|
||||
"Server status change cost must be in the registry's currency");
|
||||
checkArgument(
|
||||
instance.getRegistryLockOrUnlockBillingCost().getCurrencyUnit().equals(instance.currency),
|
||||
"Registry lock/unlock cost must be in the registry's currency");
|
||||
Predicate<Money> currencyCheck =
|
||||
(Money money) -> money.getCurrencyUnit().equals(instance.currency);
|
||||
checkArgument(
|
||||
|
||||
@@ -25,7 +25,6 @@ import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.allocateId;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -114,7 +113,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
/** Virtual parent entity for premium list entry entities associated with a single revision. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class PremiumListRevision extends ImmutableObject {
|
||||
public static class PremiumListRevision extends ImmutableObject implements DatastoreEntity {
|
||||
|
||||
@Parent Key<PremiumList> parent;
|
||||
|
||||
@@ -171,6 +170,11 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
}
|
||||
return revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // not persisted in SQL
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +196,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
@VisibleForTesting
|
||||
static LoadingCache<String, PremiumList> createCachePremiumLists(Duration cachePersistDuration) {
|
||||
return CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(cachePersistDuration.getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis()))
|
||||
.build(
|
||||
new CacheLoader<String, PremiumList>() {
|
||||
@Override
|
||||
@@ -216,7 +220,8 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
static final LoadingCache<Key<PremiumListRevision>, PremiumListRevision>
|
||||
cachePremiumListRevisions =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(getSingletonCachePersistDuration().getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(
|
||||
java.time.Duration.ofMillis(getSingletonCachePersistDuration().getMillis()))
|
||||
.build(
|
||||
new CacheLoader<Key<PremiumListRevision>, PremiumListRevision>() {
|
||||
@Override
|
||||
@@ -255,14 +260,14 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
|
||||
static LoadingCache<Key<PremiumListEntry>, Optional<PremiumListEntry>>
|
||||
createCachePremiumListEntries(Duration cachePersistDuration) {
|
||||
return CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(cachePersistDuration.getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis()))
|
||||
.maximumSize(getStaticPremiumListMaxCachedEntries())
|
||||
.build(
|
||||
new CacheLoader<Key<PremiumListEntry>, Optional<PremiumListEntry>>() {
|
||||
@Override
|
||||
public Optional<PremiumListEntry> load(final Key<PremiumListEntry> entryKey) {
|
||||
return tm()
|
||||
.doTransactionless(() -> Optional.ofNullable(ofy().load().key(entryKey).now()));
|
||||
return tm().doTransactionless(
|
||||
() -> Optional.ofNullable(ofy().load().key(entryKey).now()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration;
|
||||
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -241,7 +240,8 @@ public final class ReservedList
|
||||
|
||||
private static LoadingCache<String, ReservedList> cache =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(getDomainLabelListCacheDuration().getMillis(), MILLISECONDS)
|
||||
.expireAfterWrite(
|
||||
java.time.Duration.ofMillis(getDomainLabelListCacheDuration().getMillis()))
|
||||
.build(
|
||||
new CacheLoader<String, ReservedList>() {
|
||||
@Override
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ReservedListDualWriteDao {
|
||||
|
||||
/** Persist a new reserved list to Cloud SQL. */
|
||||
public static void save(ReservedList reservedList) {
|
||||
ofyTm().transact(() -> ofyTm().saveNewOrUpdate(reservedList));
|
||||
ofyTm().transact(() -> ofyTm().put(reservedList));
|
||||
try {
|
||||
logger.atInfo().log("Saving reserved list %s to Cloud SQL", reservedList.getName());
|
||||
ReservedListSqlDao.save(reservedList);
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ReservedListSqlDao {
|
||||
/** Persist a new reserved list to Cloud SQL. */
|
||||
public static void save(ReservedList reservedList) {
|
||||
checkArgumentNotNull(reservedList, "Must specify reservedList");
|
||||
jpaTm().transact(() -> jpaTm().saveNew(reservedList));
|
||||
jpaTm().transact(() -> jpaTm().insert(reservedList));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,8 +19,17 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
@@ -34,9 +43,17 @@ import org.joda.time.DateTime;
|
||||
* uses HistoryEntry.otherClientId because the losing party in a transfer is always the otherClient.
|
||||
*/
|
||||
@Embed
|
||||
public class DomainTransactionRecord extends ImmutableObject implements Buildable {
|
||||
@Entity
|
||||
public class DomainTransactionRecord extends ImmutableObject
|
||||
implements Buildable, DatastoreAndSqlEntity {
|
||||
|
||||
@Id
|
||||
@Ignore
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
/** The TLD this record operates on. */
|
||||
@Column(nullable = false)
|
||||
String tld;
|
||||
|
||||
/**
|
||||
@@ -50,9 +67,12 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||
* href="https://www.icann.org/resources/unthemed-pages/registry-agmt-appc-10-2001-05-11-en">
|
||||
* Grace period spec</a>
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
DateTime reportingTime;
|
||||
|
||||
/** The transaction report field we add reportAmount to for this registrar. */
|
||||
@Column(nullable = false)
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
TransactionReportField reportField;
|
||||
|
||||
/**
|
||||
@@ -67,6 +87,7 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||
* original SUCCESSFUL transfer counters. Finally, if we explicitly allow a transfer, the report
|
||||
* amount is 0, as we've already counted the transfer in the original request.
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
Integer reportAmount;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.googlecode.objectify.Key.getKind;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
@@ -40,17 +41,18 @@ import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -59,7 +61,8 @@ import org.joda.time.DateTime;
|
||||
@Entity
|
||||
@MappedSuperclass
|
||||
@WithStringVKey // TODO(b/162229294): This should be resolved during the course of that bug
|
||||
public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
@Access(AccessType.FIELD)
|
||||
public class HistoryEntry extends ImmutableObject implements Buildable, DatastoreEntity {
|
||||
|
||||
/** Represents the type of history entry. */
|
||||
public enum Type {
|
||||
@@ -110,17 +113,13 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
SYNTHETIC
|
||||
}
|
||||
|
||||
/** The autogenerated id of this event. */
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator")
|
||||
@SequenceGenerator(
|
||||
name = "HistorySequenceGenerator",
|
||||
sequenceName = "history_id_sequence",
|
||||
allocationSize = 1)
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@Column(name = "historyRevisionId")
|
||||
@VisibleForTesting
|
||||
public Long id;
|
||||
/**
|
||||
* The autogenerated id of this event. Note that, this field is marked as {@link Transient} in the
|
||||
* SQL schema, this is because the child class of {@link HistoryEntry}, e.g. {@link
|
||||
* DomainHistory}, uses a composite primary key which the id is part of, and Hibernate requires
|
||||
* that all the {@link javax.persistence.Id} fields must be put in the exact same class.
|
||||
*/
|
||||
@Id @Transient @VisibleForTesting public Long id;
|
||||
|
||||
/** The resource this event mutated. */
|
||||
@Parent @Transient protected Key<? extends EppResource> parent;
|
||||
@@ -179,7 +178,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
boolean bySuperuser;
|
||||
|
||||
/** Reason for the change. */
|
||||
@Column(nullable = false, name = "historyReason")
|
||||
@Column(name = "historyReason")
|
||||
String reason;
|
||||
|
||||
/** Whether this change was requested by a registrar. */
|
||||
@@ -196,8 +195,17 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
@Transient // domain-specific
|
||||
Set<DomainTransactionRecord> domainTransactionRecords;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
public long getId() {
|
||||
// For some reason, Hibernate throws NPE during some initialization phase if we don't deal with
|
||||
// the null case. Setting the id to 0L when it is null should be fine because 0L for primitive
|
||||
// type is considered as null for wrapper class in the Hibernate context.
|
||||
return id == null ? 0L : id;
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Key<? extends EppResource> getParent() {
|
||||
@@ -246,10 +254,28 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
return requestedByRegistrar;
|
||||
}
|
||||
|
||||
public ImmutableSet<DomainTransactionRecord> getDomainTransactionRecords() {
|
||||
public Set<DomainTransactionRecord> getDomainTransactionRecords() {
|
||||
return nullToEmptyImmutableCopy(domainTransactionRecords);
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setPeriod(Period period) {
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setOtherRegistrarId(String otherRegistrarId) {
|
||||
this.otherClientId = otherRegistrarId;
|
||||
}
|
||||
|
||||
/** This method exists solely to satisfy Hibernate. Use the {@link Builder} instead. */
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void setDomainTransactionRecords(Set<DomainTransactionRecord> domainTransactionRecords) {
|
||||
this.domainTransactionRecords = ImmutableSet.copyOf(domainTransactionRecords);
|
||||
}
|
||||
|
||||
public static VKey<HistoryEntry> createVKey(Key<HistoryEntry> key) {
|
||||
// TODO(b/159207551): This will likely need some revision. As it stands, this method was
|
||||
// introduced purely to facilitate testing of VKey specialization in VKeyTranslatorFactory.
|
||||
@@ -279,26 +305,13 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
// can't use a switch statement since we're calling getKind()
|
||||
if (parentKind.equals(getKind(DomainBase.class))) {
|
||||
resultEntity =
|
||||
new DomainHistory.Builder()
|
||||
.copyFrom(this)
|
||||
.setDomainRepoId(
|
||||
VKey.create(DomainBase.class, parent.getName(), (Key<DomainBase>) parent))
|
||||
.build();
|
||||
new DomainHistory.Builder().copyFrom(this).setDomainRepoId(parent.getName()).build();
|
||||
} else if (parentKind.equals(getKind(HostResource.class))) {
|
||||
resultEntity =
|
||||
new HostHistory.Builder()
|
||||
.copyFrom(this)
|
||||
.setHostRepoId(
|
||||
VKey.create(HostResource.class, parent.getName(), (Key<HostResource>) parent))
|
||||
.build();
|
||||
new HostHistory.Builder().copyFrom(this).setHostRepoId(parent.getName()).build();
|
||||
} else if (parentKind.equals(getKind(ContactResource.class))) {
|
||||
resultEntity =
|
||||
new ContactHistory.Builder()
|
||||
.copyFrom(this)
|
||||
.setContactRepoId(
|
||||
VKey.create(
|
||||
ContactResource.class, parent.getName(), (Key<ContactResource>) parent))
|
||||
.build();
|
||||
new ContactHistory.Builder().copyFrom(this).setContactRepoId(parent.getName()).build();
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format("Unknown kind of HistoryEntry parent %s", parentKind));
|
||||
@@ -306,6 +319,12 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
return resultEntity;
|
||||
}
|
||||
|
||||
// In SQL, save the child type
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of((SqlEntity) toChildHistoryEntity());
|
||||
}
|
||||
|
||||
/** A builder for {@link HistoryEntry} since it is immutable */
|
||||
public static class Builder<T extends HistoryEntry, B extends Builder<?, ?>>
|
||||
extends GenericBuilder<T, B> {
|
||||
@@ -330,7 +349,10 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
setBySuperuser(historyEntry.bySuperuser);
|
||||
setReason(historyEntry.reason);
|
||||
setRequestedByRegistrar(historyEntry.requestedByRegistrar);
|
||||
setDomainTransactionRecords(nullToEmptyImmutableCopy(historyEntry.domainTransactionRecords));
|
||||
setDomainTransactionRecords(
|
||||
historyEntry.domainTransactionRecords == null
|
||||
? null
|
||||
: ImmutableSet.copyOf(historyEntry.domainTransactionRecords));
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
@@ -349,6 +371,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
// Until we move completely to SQL, override this in subclasses (e.g. HostHistory) to set VKeys
|
||||
public B setParent(Key<? extends EppResource> parent) {
|
||||
getInstance().parent = parent;
|
||||
return thisCastToDerived();
|
||||
|
||||
@@ -75,7 +75,7 @@ public class Spec11ThreatMatch extends ImmutableObject implements Buildable, Sql
|
||||
String registrarId;
|
||||
|
||||
/** Date on which the check was run, on which the domain was flagged as abusive. */
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = false, columnDefinition = "date")
|
||||
LocalDate checkDate;
|
||||
|
||||
/** The domain's top-level domain. */
|
||||
|
||||
@@ -16,23 +16,25 @@ package google.registry.model.reporting;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import javax.persistence.TemporalType;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Data access object for {@link google.registry.model.reporting.Spec11ThreatMatch}.
|
||||
*
|
||||
* <p>A JpaTransactionManager is passed into each static method because they are called from a BEAM
|
||||
* pipeline and we don't know where it's coming from.</p>
|
||||
* pipeline and we don't know where it's coming from.
|
||||
*/
|
||||
public class Spec11ThreatMatchDao {
|
||||
|
||||
|
||||
/** Delete all entries with the specified date from the database. */
|
||||
public static void deleteEntriesByDate(JpaTransactionManager jpaTm, LocalDate date) {
|
||||
jpaTm.assertInTransaction();
|
||||
jpaTm
|
||||
.getEntityManager()
|
||||
.createQuery("DELETE FROM Spec11ThreatMatch WHERE check_date = :date")
|
||||
.setParameter("date", date.toString())
|
||||
.setParameter("date", DateTimeUtils.toSqlDate(date), TemporalType.DATE)
|
||||
.executeUpdate();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.tmch;
|
||||
package google.registry.model.tmch;
|
||||
|
||||
import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration;
|
||||
import static google.registry.model.CacheUtils.tryMemoizeWithExpiration;
|
||||
@@ -24,28 +24,28 @@ import google.registry.util.NonFinalForTesting;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/** Data access object for {@link ClaimsList}. */
|
||||
/** Data access object for {@link ClaimsListShard}. */
|
||||
public class ClaimsListDao {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/** In-memory cache for claims list. */
|
||||
@NonFinalForTesting
|
||||
private static Supplier<Optional<ClaimsList>> cacheClaimsList =
|
||||
private static Supplier<Optional<ClaimsListShard>> cacheClaimsList =
|
||||
tryMemoizeWithExpiration(getDomainLabelListCacheDuration(), ClaimsListDao::getLatestRevision);
|
||||
|
||||
private static void save(ClaimsList claimsList) {
|
||||
private static void save(ClaimsListShard claimsList) {
|
||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(claimsList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to save the given {@link ClaimsList} into Cloud SQL. If the save fails, the error will be
|
||||
* logged but no exception will be thrown.
|
||||
* Try to save the given {@link ClaimsListShard} into Cloud SQL. If the save fails, the error will
|
||||
* be logged but no exception will be thrown.
|
||||
*
|
||||
* <p>This method is used during the dual-write phase of database migration as Datastore is still
|
||||
* the authoritative database.
|
||||
*/
|
||||
public static void trySave(ClaimsList claimsList) {
|
||||
static void trySave(ClaimsListShard claimsList) {
|
||||
try {
|
||||
ClaimsListDao.save(claimsList);
|
||||
logger.atInfo().log(
|
||||
@@ -57,12 +57,12 @@ public class ClaimsListDao {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most recent revision of the {@link ClaimsList} in Cloud SQL, if it exists.
|
||||
* Returns the most recent revision of the {@link ClaimsListShard} in Cloud SQL, if it exists.
|
||||
* TODO(shicong): Change this method to package level access after dual-read phase.
|
||||
* ClaimsListShard uses this method to retrieve claims list in Cloud SQL for the comparison, and
|
||||
* ClaimsListShard is not in this package.
|
||||
*/
|
||||
public static Optional<ClaimsList> getLatestRevision() {
|
||||
public static Optional<ClaimsListShard> getLatestRevision() {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
@@ -73,15 +73,15 @@ public class ClaimsListDao {
|
||||
return em.createQuery(
|
||||
"FROM ClaimsList cl LEFT JOIN FETCH cl.labelsToKeys WHERE cl.revisionId ="
|
||||
+ " :revisionId",
|
||||
ClaimsList.class)
|
||||
ClaimsListShard.class)
|
||||
.setParameter("revisionId", revisionId)
|
||||
.getResultStream()
|
||||
.findFirst();
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the most recent revision of the {@link ClaimsList}, from cache. */
|
||||
public static Optional<ClaimsList> getLatestRevisionCached() {
|
||||
/** Returns the most recent revision of the {@link ClaimsListShard}, from cache. */
|
||||
public static Optional<ClaimsListShard> getLatestRevisionCached() {
|
||||
return cacheClaimsList.get();
|
||||
}
|
||||
|
||||
@@ -40,15 +40,15 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.OnSave;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.schema.replay.DatastoreEntity;
|
||||
import google.registry.schema.replay.SqlEntity;
|
||||
import google.registry.schema.tmch.ClaimsList;
|
||||
import google.registry.schema.tmch.ClaimsListDao;
|
||||
import google.registry.util.CollectionUtils;
|
||||
import google.registry.util.Concurrent;
|
||||
import google.registry.util.Retrier;
|
||||
@@ -57,8 +57,16 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
@@ -74,38 +82,70 @@ import org.joda.time.DateTime;
|
||||
* 10MB per transaction limit.
|
||||
*
|
||||
* <p>Therefore, it is never OK to save an instance of this class directly to Datastore. Instead you
|
||||
* must use the {@link #save} method to do it for you.
|
||||
* must use the {@link #saveToDatastore} method to do it for you.
|
||||
*
|
||||
* <p>Note that the primary key of this entity is {@link #revisionId}, which is auto-generated by
|
||||
* the database. So, if a retry of insertion happens after the previous attempt unexpectedly
|
||||
* succeeds, we will end up with having two exact same claims list with only different {@link
|
||||
* #revisionId}. However, this is not an actual problem because we only use the claims list with
|
||||
* highest {@link #revisionId}.
|
||||
*
|
||||
* <p>TODO(b/162007765): Rename the class to ClaimsList and remove Datastore related fields and
|
||||
* methods.
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.EXTERNALLY_SOURCED)
|
||||
public class ClaimsListShard extends ImmutableObject implements DatastoreEntity {
|
||||
@javax.persistence.Entity(name = "ClaimsList")
|
||||
@Table
|
||||
public class ClaimsListShard extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/** The number of claims list entries to store per shard. */
|
||||
private static final int SHARD_SIZE = 10000;
|
||||
|
||||
@Id
|
||||
long id;
|
||||
@Transient @Id long id;
|
||||
|
||||
@Parent
|
||||
Key<ClaimsListRevision> parent;
|
||||
@Transient @Parent Key<ClaimsListRevision> parent;
|
||||
|
||||
/** When the claims list was last updated. */
|
||||
@Ignore
|
||||
@javax.persistence.Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long revisionId;
|
||||
|
||||
@Ignore
|
||||
@Column(nullable = false)
|
||||
CreateAutoTimestamp creationTimestamp = CreateAutoTimestamp.create(null);
|
||||
|
||||
/**
|
||||
* When the claims list was last updated.
|
||||
*
|
||||
* <p>Note that the value of this field is parsed from the claims list file(See this <a
|
||||
* href="https://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.1">RFC</>), it is
|
||||
* the DNL List creation datetime from the rfc. Since this field has been used by Datastore, we
|
||||
* cannot change its name until we finish the migration.
|
||||
*
|
||||
* <p>TODO(b/166784536): Rename this field to tmdbGenerationTime.
|
||||
*/
|
||||
@Column(name = "tmdb_generation_time", nullable = false)
|
||||
DateTime creationTime;
|
||||
|
||||
/** A map from labels to claims keys. */
|
||||
@EmbedMap
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "ClaimsEntry",
|
||||
joinColumns = @JoinColumn(name = "revisionId", referencedColumnName = "revisionId"))
|
||||
@MapKeyColumn(name = "domainLabel", nullable = false)
|
||||
@Column(name = "claimKey", nullable = false)
|
||||
Map<String, String> labelsToKeys;
|
||||
|
||||
/** Indicates that this is a shard rather than a "full" list. */
|
||||
@Ignore
|
||||
boolean isShard = false;
|
||||
@Ignore @Transient boolean isShard = false;
|
||||
|
||||
private static final Retrier LOADER_RETRIER = new Retrier(new SystemSleeper(), 2);
|
||||
|
||||
private static final Callable<ClaimsListShard> LOADER_CALLABLE =
|
||||
() -> {
|
||||
private static ClaimsListShard loadClaimsListShard() {
|
||||
// Find the most recent revision.
|
||||
Key<ClaimsListRevision> revisionKey = getCurrentRevision();
|
||||
|
||||
@@ -164,10 +204,10 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
return datastoreList;
|
||||
};
|
||||
|
||||
private static final void loadAndCompareCloudSqlList(ClaimsListShard datastoreList) {
|
||||
Optional<ClaimsList> maybeCloudSqlList = ClaimsListDao.getLatestRevision();
|
||||
private static void loadAndCompareCloudSqlList(ClaimsListShard datastoreList) {
|
||||
Optional<ClaimsListShard> maybeCloudSqlList = ClaimsListDao.getLatestRevision();
|
||||
if (maybeCloudSqlList.isPresent()) {
|
||||
ClaimsList cloudSqlList = maybeCloudSqlList.get();
|
||||
ClaimsListShard cloudSqlList = maybeCloudSqlList.get();
|
||||
MapDifference<String, String> diff =
|
||||
Maps.difference(datastoreList.labelsToKeys, cloudSqlList.getLabelsToKeys());
|
||||
if (!diff.areEqual()) {
|
||||
@@ -204,17 +244,38 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
*/
|
||||
private static final Supplier<ClaimsListShard> CACHE =
|
||||
memoizeWithShortExpiration(
|
||||
() -> LOADER_RETRIER.callWithRetry(LOADER_CALLABLE, IllegalStateException.class));
|
||||
() ->
|
||||
LOADER_RETRIER.callWithRetry(
|
||||
ClaimsListShard::loadClaimsListShard, IllegalStateException.class));
|
||||
|
||||
public DateTime getCreationTime() {
|
||||
/** Returns the revision id of this claims list, or throws exception if it is null. */
|
||||
public Long getRevisionId() {
|
||||
checkState(
|
||||
revisionId != null, "revisionId is null because it is not persisted in the database");
|
||||
return revisionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time when the external TMDB service generated this revision of the claims list.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/draft-lozano-tmch-func-spec-08#section-6.1">DNL List
|
||||
* creation datetime</a>
|
||||
*/
|
||||
public DateTime getTmdbGenerationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
/** Returns the creation time of this claims list. */
|
||||
public DateTime getCreationTimestamp() {
|
||||
return creationTimestamp.getTimestamp();
|
||||
}
|
||||
|
||||
/** Returns the claim key for a given domain if there is one, empty otherwise. */
|
||||
public Optional<String> getClaimKey(String label) {
|
||||
return Optional.ofNullable(labelsToKeys.get(label));
|
||||
}
|
||||
|
||||
/** Returns an {@link Map} mapping domain label to its lookup key. */
|
||||
public ImmutableMap<String, String> getLabelsToKeys() {
|
||||
return ImmutableMap.copyOf(labelsToKeys);
|
||||
}
|
||||
@@ -229,11 +290,12 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
* switching over to using them atomically, then deleting the old ones.
|
||||
*/
|
||||
public void save() {
|
||||
save(SHARD_SIZE);
|
||||
saveToDatastore(SHARD_SIZE);
|
||||
ClaimsListDao.trySave(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void save(int shardSize) {
|
||||
void saveToDatastore(int shardSize) {
|
||||
// Figure out what the next versionId should be based on which ones already exist.
|
||||
final Key<ClaimsListRevision> oldRevision = getCurrentRevision();
|
||||
final Key<ClaimsListRevision> parentKey = ClaimsListRevision.createKey();
|
||||
@@ -270,10 +332,11 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
});
|
||||
}
|
||||
|
||||
public static ClaimsListShard create(DateTime creationTime, Map<String, String> labelsToKeys) {
|
||||
public static ClaimsListShard create(
|
||||
DateTime tmdbGenerationTime, Map<String, String> labelsToKeys) {
|
||||
ClaimsListShard instance = new ClaimsListShard();
|
||||
instance.id = allocateId();
|
||||
instance.creationTime = checkNotNull(creationTime);
|
||||
instance.creationTime = checkNotNull(tmdbGenerationTime);
|
||||
instance.labelsToKeys = checkNotNull(labelsToKeys);
|
||||
return instance;
|
||||
}
|
||||
@@ -292,11 +355,6 @@ public class ClaimsListShard extends ImmutableObject implements DatastoreEntity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<SqlEntity> toSqlEntities() {
|
||||
return ImmutableList.of(); // ClaimsLists are dually written
|
||||
}
|
||||
|
||||
/** Virtual parent entity for claims list shards of a specific revision. */
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user