1
0
mirror of https://github.com/google/nomulus synced 2026-02-02 19:12:27 +00:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Lai Jiang
7309a79129 Check for null error stream (#2249) 2023-12-06 14:07:25 -05:00
Pavlo Tkach
65d6382b6a Increase number of service to 5 in cloudbuild-deploy (#2248) 2023-12-06 14:07:15 -05:00
Lai Jiang
c7bc51c1d0 Use the error stream when HTTP response code is non-200 (#2245) 2023-12-06 14:07:07 -05:00
641 changed files with 35644 additions and 29022 deletions

View File

@@ -7,7 +7,7 @@ on:
# The branches below must be a subset of the branches above
branches: [ 'master' ]
schedule:
- cron: '24 4 * * *'
- cron: '24 4 * * 2'
jobs:
analyze:
@@ -27,17 +27,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Set Java version
uses: actions/setup-java@v4
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '21'
java-version: '11'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -47,20 +47,11 @@ jobs:
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
queries: security-and-quality
# Build with Gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
build-scan-publish: true
build-scan-terms-of-service-url: "https://gradle.com/terms-of-service"
build-scan-terms-of-service-agree: "yes"
- name: Execute Gradle build
run: ./gradlew build -x test -x jIFC
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
#- name: Autobuild
# uses: github/codeql-action/autobuild@v3
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -73,6 +64,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@@ -1,25 +0,0 @@
name: Dependency Submission
on:
push:
branches: [ 'master' ]
schedule:
- cron: '24 3 * * *'
permissions:
contents: write
jobs:
dependency-submission:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Set Java version
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v3

View File

@@ -1,23 +0,0 @@
name: "Check labels"
on:
pull_request:
branches: ["master"]
types:
- opened
- synchronize
- labeled
- unlabeled
merge_group:
branches: ["master"]
types: [checks_requested]
jobs:
fail-by-label:
runs-on: ubuntu-latest
steps:
- name: Fail if PR is labeled as "do not merge"
if: contains(github.event.pull_request.labels.*.name, 'do not merge')
run: |
echo "This PR is labeled as do not merge!"
exit 1

3
.gitignore vendored
View File

@@ -117,6 +117,3 @@ core/**/registrar_dbg*.css
# Appengine generated files
core/WEB-INF/appengine-generated/*.bin
core/WEB-INF/appengine-generated/*.xml
# jEnv
.java-version

View File

@@ -1 +0,0 @@
21

View File

@@ -29,7 +29,7 @@ buildscript {
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.1'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:3.1.0'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:2.0.2'
classpath 'org.sonatype.aether:aether-api:1.13.1'
classpath 'org.sonatype.aether:aether-impl:1.13.1'
}
@@ -41,9 +41,9 @@ plugins {
// Re-enable when compatible with Gradle 8
// id 'nebula.lint' version '16.0.2'
id 'net.ltgt.errorprone' version '3.1.0'
id 'net.ltgt.errorprone' version '2.0.2'
id 'checkstyle'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'com.github.johnrengelman.shadow' version '5.1.0'
// NodeJs plugin
id "com.github.node-gradle.node" version "3.0.1"
@@ -61,7 +61,7 @@ dependencyLocking {
node {
download = false
version = "20.10.0"
version = "16.19.0"
}
wrapper {
@@ -211,30 +211,6 @@ allprojects {
options.fork = true
options.forkOptions.executable =
file("${System.env.JAVA_HOME}/bin/javac")
options.compilerArgs = ["--add-exports",
"jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"--add-exports",
"jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
options.forkOptions.jvmArgs = ["-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
}
}
}
@@ -281,12 +257,6 @@ def javadocSource = []
def javadocClasspath = []
def javadocDependentTasks = []
def services = [':services:default',
':services:backend',
':services:bsa',
':services:tools',
':services:pubapi']
subprojects {
// Skip no-op project
if (project.name == 'services') return
@@ -337,7 +307,8 @@ subprojects {
afterEvaluate {
if (rootProject.enableDependencyLocking.toBoolean()
&& project.name != 'integration') {
&& project.name != 'integration'
&& project.name != 'java8compatibility') {
// The ':integration' project runs server/schema integration tests using
// dynamically specified jars with no transitive dependency. Therefore
// dependency-locking does not make sense. Furthermore, during
@@ -345,6 +316,9 @@ subprojects {
// immutable. Locking activation would trigger an invalid operation
// exception.
//
// The ':java8compatibility' project is test-only. Its source does not go
// into production.
//
// For all other projects, due to problem with the gradle-license-report
// plugin, the dependencyLicenseReport configuration must opt out of
// dependency-locking. See dependency_lic.gradle for the reason why.
@@ -360,6 +334,23 @@ subprojects {
}
}
// 'listenablefuture' is folded into guava since v32. This block is required
// until all transitive dependencies have upgraded past guava v32.
// TODO(periodically): remove this block and see if build succeeds.
configurations.all {
resolutionStrategy
.capabilitiesResolution
.withCapability("com.google.guava:listenablefuture") {
select("com.google.guava:guava:0")
}
}
def services = [':services:default',
':services:backend',
':services:bsa',
':services:tools',
':services:pubapi']
// Set up all of the deployment projects.
if (services.contains(project.path)) {
@@ -371,12 +362,12 @@ subprojects {
apply from: "${rootDir.path}/java_common.gradle"
// When changing Java version here, be sure to update BEAM Java runtime:
// search for `flex-template-base-image` and update the parameter value.
// There are at least two instances, one in core/build.gradle, one in
// release/stage_beam_pipeline.sh
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
if (project.name != 'docs') {
compileJava {
// TODO: Remove this once we migrate off AppEngine.
options.release = 8
}
}
project.tasks.test.dependsOn runPresubmits
@@ -401,9 +392,9 @@ subprojects {
}
}
// No need to produce javadoc for the jetty subproject, which has no APIs to
// No need to produce javadoc for the docs subproject, which has no APIs to
// expose to users.
if (project.name != 'jetty') {
if (project.name != 'docs') {
javadocSource << project.sourceSets.main.allJava
javadocClasspath << project.sourceSets.main.runtimeClasspath
javadocClasspath << "${buildDir}/generated/sources/annotationProcessor/java/main"
@@ -411,17 +402,6 @@ subprojects {
}
}
// Force SDK download and deployment to be sequential, otherwise parallel tasks
// will fail. For SDK download, they will try to write to the same location to
// upgrade gcloud. For deployment, they will try to deploy different services to
// the same project at the same time.
for (int i = 1; i < services.size(); i++) {
project("${services[i]}").downloadCloudSdk
.dependsOn(project("${services[i - 1]}").downloadCloudSdk)
project("${services[i]}").appengineDeployAll
.dependsOn(project("${services[i - 1]}").appengineDeployAll)
}
// If "-P verboseTestOutput=true" is passed in, configure all subprojects to dump all of their
// output and final test status (pass/fail, errors) for each test class.
//
@@ -499,14 +479,10 @@ def createGetBuildSrcDirectDepsTask(outputFileName) {
rootProject.ext {
invokeJavaDiffFormatScript = { action ->
def javaHome = project.findProperty('org.gradle.java.home')
def javaBin
if (javaHome != null) {
javaBin = "$javaHome/bin/java"
} else {
javaBin = ext.execInBash("which java", rootDir)
}
println("Running the formatting tool with $javaBin")
println("JAVA_HOME=${System.env.JAVA_HOME}")
println("PATH=${System.env.PATH}")
println(ext.execInBash("type java", "${rootDir}"))
println(ext.execInBash("java -version", "${rootDir}"))
def scriptDir = rootDir.path.endsWith('buildSrc')
? "${rootDir}/../java-format"
: "${rootDir}/java-format"
@@ -517,7 +493,7 @@ rootProject.ext {
def pythonExe = getPythonExecutable()
return ext.execInBash(
"JAVA=${javaBin} PYTHON=${pythonExe} ${formatDiffScript} ${action}", "${workingDir}")
"PYTHON=${pythonExe} ${formatDiffScript} ${action}", "${workingDir}")
}
}
@@ -572,9 +548,7 @@ task javadoc(type: Javadoc) {
destinationDir = file("${buildDir}/docs/javadoc")
options.encoding = "UTF-8"
// In a lot of places we don't write @return so suppress warnings about that.
// We don't report HTML lint errors because XJB-generated POJO files have
// incorrect tags (like dangling </p> without the corresponding open tag.
options.addBooleanOption('Xdoclint:all,-missing,-html', true)
options.addBooleanOption('Xdoclint:all,-missing', true)
options.addBooleanOption("-allow-script-in-comments",true)
options.tags = ["type:a:Generic Type",
"error:a:Expected Error",
@@ -592,8 +566,7 @@ task coreDev {
dependsOn 'javadoc'
dependsOn 'checkDependenciesDotGradle'
dependsOn 'checkLicense'
// TODO: @ptkach reenable after console design merged
// dependsOn ':console-webapp:runConsoleWebappUnitTests'
dependsOn ':console-webapp:runConsoleWebappUnitTests'
dependsOn ':core:check'
dependsOn 'assemble'
}

View File

@@ -36,7 +36,7 @@ plugins {
// We don't anticipate enabling the Gradle lint plugin because they will not support Kotlin
// See https://github.com/nebula-plugins/gradle-lint-plugin/issues/166
// id 'nebula.lint' version '16.0.2'
id("net.ltgt.errorprone") version "3.1.0"
id("net.ltgt.errorprone") version "2.0.2"
checkstyle
id("com.diffplug.spotless") version "6.20.0"
}
@@ -104,6 +104,8 @@ dependencies {
implementation(deps["org.apache.commons:commons-text"]!!)
annotationProcessor(deps["com.google.auto.value:auto-value"]!!)
testImplementation(deps["com.google.truth:truth"]!!)
testImplementation(
deps["com.google.truth.extensions:truth-java8-extension"]!!)
testImplementation(deps["org.junit.jupiter:junit-jupiter-api"]!!)
testImplementation(deps["org.junit.jupiter:junit-jupiter-engine"]!!)
testImplementation(deps["org.mockito:mockito-core"]!!)

View File

@@ -15,14 +15,14 @@ com.squareup.okhttp3:okhttp:4.10.0=classpath
com.squareup.okio:okio-jvm:3.0.0=classpath
com.squareup.okio:okio:3.0.0=classpath
dev.equo.ide:solstice:1.3.1=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:3.1.0=classpath
net.ltgt.gradle:gradle-errorprone-plugin:3.1.0=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:2.0.2=classpath
net.ltgt.gradle:gradle-errorprone-plugin:2.0.2=classpath
org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r=classpath
org.eclipse.platform:org.eclipse.osgi:3.18.300=classpath
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.20=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0=classpath
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=classpath
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0=classpath
org.jetbrains.kotlin:kotlin-stdlib:1.9.0=classpath
org.jetbrains:annotations:13.0=classpath
org.slf4j:slf4j-api:1.7.36=classpath
org.tukaani:xz:1.9=classpath

View File

@@ -1,101 +1,99 @@
# 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.
aopalliance:aopalliance:1.0=annotationProcessor,buildScriptClasspath,compileClasspath
aopalliance:aopalliance:1.0=buildScriptClasspath,compileClasspath
args4j:args4j:2.0.23=buildScriptClasspath,compileClasspath
com.fasterxml.jackson.core:jackson-core:2.16.1=buildScriptClasspath,compileClasspath
com.fasterxml.jackson:jackson-bom:2.16.1=buildScriptClasspath,compileClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor
com.fasterxml.jackson.core:jackson-core:2.14.2=buildScriptClasspath,compileClasspath
com.fasterxml.jackson:jackson-bom:2.14.2=buildScriptClasspath,compileClasspath
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor
com.google.android:annotations:4.1.1.4=buildScriptClasspath
com.google.api-client:google-api-client:2.3.0=buildScriptClasspath,compileClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.35.0-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-common-protos:2.36.0=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-iam-v1:1.31.0=buildScriptClasspath,compileClasspath
com.google.api:api-common:2.28.0=buildScriptClasspath,compileClasspath
com.google.api:gax-grpc:2.45.0=buildScriptClasspath,compileClasspath
com.google.api:gax-httpjson:2.45.0=buildScriptClasspath,compileClasspath
com.google.api:gax:2.45.0=buildScriptClasspath,compileClasspath
com.google.apis:google-api-services-storage:v1-rev20240209-2.0.0=buildScriptClasspath,compileClasspath
com.google.auth:google-auth-library-credentials:1.23.0=buildScriptClasspath,compileClasspath
com.google.auth:google-auth-library-oauth2-http:1.23.0=buildScriptClasspath,compileClasspath
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor
com.google.auto.value:auto-value-annotations:1.10.4=buildScriptClasspath,compileClasspath
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor
com.google.api-client:google-api-client:2.2.0=buildScriptClasspath,compileClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.22.6-alpha=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-common-protos:2.22.0=buildScriptClasspath,compileClasspath
com.google.api.grpc:proto-google-iam-v1:1.17.0=buildScriptClasspath,compileClasspath
com.google.api:api-common:2.14.0=buildScriptClasspath,compileClasspath
com.google.api:gax-grpc:2.31.0=buildScriptClasspath,compileClasspath
com.google.api:gax-httpjson:2.31.0=buildScriptClasspath,compileClasspath
com.google.api:gax:2.31.0=buildScriptClasspath,compileClasspath
com.google.apis:google-api-services-storage:v1-rev20230301-2.0.0=buildScriptClasspath,compileClasspath
com.google.auth:google-auth-library-credentials:1.19.0=buildScriptClasspath,compileClasspath
com.google.auth:google-auth-library-oauth2-http:1.19.0=buildScriptClasspath,compileClasspath
com.google.auto.value:auto-value-annotations:1.10.1=buildScriptClasspath,compileClasspath
com.google.auto.value:auto-value:1.10.4=annotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor
com.google.cloud:google-cloud-core-grpc:2.35.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-core-http:2.35.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-core:2.35.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-storage:2.35.0=buildScriptClasspath,compileClasspath
com.google.auto:auto-common:0.10=annotationProcessor
com.google.cloud:google-cloud-core-grpc:2.21.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-core-http:2.21.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-core:2.21.0=buildScriptClasspath,compileClasspath
com.google.cloud:google-cloud-storage:2.22.6=buildScriptClasspath,compileClasspath
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,buildScriptClasspath,compileClasspath
com.google.code.gson:gson:2.10.1=buildScriptClasspath,compileClasspath
com.google.common.html.types:types:1.0.6=buildScriptClasspath,compileClasspath
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor
com.google.errorprone:error_prone_annotations:2.26.1=buildScriptClasspath,compileClasspath
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor
com.google.errorprone:error_prone_annotations:2.18.0=buildScriptClasspath,compileClasspath
com.google.errorprone:error_prone_annotations:2.3.4=annotationProcessor
com.google.errorprone:error_prone_check_api:2.3.4=annotationProcessor
com.google.errorprone:error_prone_core:2.3.4=annotationProcessor
com.google.errorprone:error_prone_type_annotations:2.3.4=annotationProcessor
com.google.escapevelocity:escapevelocity:0.9.1=buildScriptClasspath,compileClasspath
com.google.guava:failureaccess:1.0.1=annotationProcessor
com.google.guava:failureaccess:1.0.2=buildScriptClasspath,compileClasspath
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor
com.google.guava:guava:32.1.1-jre=annotationProcessor
com.google.guava:guava:33.1.0-jre=buildScriptClasspath,compileClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-apache-v2:1.44.1=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-appengine:1.44.1=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-gson:1.44.1=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-jackson2:1.44.1=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client:1.44.1=buildScriptClasspath,compileClasspath
com.google.guava:failureaccess:1.0.1=annotationProcessor,buildScriptClasspath,compileClasspath
com.google.guava:guava-parent:32.1.1-jre=buildScriptClasspath,compileClasspath
com.google.guava:guava:27.0.1-jre=annotationProcessor
com.google.guava:guava:32.1.1-jre=buildScriptClasspath,compileClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor
com.google.http-client:google-http-client-apache-v2:1.43.3=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-appengine:1.43.3=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-gson:1.43.3=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client-jackson2:1.43.3=buildScriptClasspath,compileClasspath
com.google.http-client:google-http-client:1.43.3=buildScriptClasspath,compileClasspath
com.google.inject.extensions:guice-multibindings:4.1.0=buildScriptClasspath,compileClasspath
com.google.inject:guice:4.1.0=buildScriptClasspath,compileClasspath
com.google.inject:guice:5.1.0=annotationProcessor
com.google.j2objc:j2objc-annotations:2.8=buildScriptClasspath
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath
com.google.j2objc:j2objc-annotations:1.1=annotationProcessor
com.google.j2objc:j2objc-annotations:2.8=buildScriptClasspath,compileClasspath
com.google.jsinterop:jsinterop-annotations:1.0.1=buildScriptClasspath,compileClasspath
com.google.oauth-client:google-oauth-client:1.35.0=buildScriptClasspath,compileClasspath
com.google.protobuf:protobuf-java-util:3.25.2=buildScriptClasspath,compileClasspath
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor
com.google.protobuf:protobuf-java:3.25.2=buildScriptClasspath,compileClasspath
com.google.re2j:re2j:1.7=buildScriptClasspath
com.google.oauth-client:google-oauth-client:1.34.1=buildScriptClasspath,compileClasspath
com.google.protobuf:protobuf-java-util:3.23.2=buildScriptClasspath,compileClasspath
com.google.protobuf:protobuf-java:3.23.2=buildScriptClasspath,compileClasspath
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor
com.google.re2j:re2j:1.6=buildScriptClasspath
com.google.template:soy:2021-02-01=buildScriptClasspath,compileClasspath
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor
com.ibm.icu:icu4j:57.1=buildScriptClasspath,compileClasspath
commons-codec:commons-codec:1.16.1=buildScriptClasspath,compileClasspath
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor
io.grpc:grpc-alts:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-api:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-auth:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-context:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-core:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-googleapis:1.62.2=buildScriptClasspath
io.grpc:grpc-grpclb:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-inprocess:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-netty-shaded:1.62.2=buildScriptClasspath
io.grpc:grpc-protobuf-lite:1.62.2=buildScriptClasspath
io.grpc:grpc-protobuf:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-rls:1.62.2=buildScriptClasspath
io.grpc:grpc-services:1.62.2=buildScriptClasspath
io.grpc:grpc-stub:1.62.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-util:1.62.2=buildScriptClasspath
io.grpc:grpc-xds:1.62.2=buildScriptClasspath
commons-codec:commons-codec:1.15=buildScriptClasspath,compileClasspath
commons-logging:commons-logging:1.2=buildScriptClasspath,compileClasspath
io.grpc:grpc-alts:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-api:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-auth:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-context:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-core:1.55.3=buildScriptClasspath
io.grpc:grpc-googleapis:1.55.3=buildScriptClasspath
io.grpc:grpc-grpclb:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-netty-shaded:1.55.3=buildScriptClasspath
io.grpc:grpc-protobuf-lite:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-protobuf:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-rls:1.55.3=buildScriptClasspath
io.grpc:grpc-services:1.55.3=buildScriptClasspath
io.grpc:grpc-stub:1.55.3=buildScriptClasspath,compileClasspath
io.grpc:grpc-xds:1.55.3=buildScriptClasspath
io.opencensus:opencensus-api:0.31.1=buildScriptClasspath,compileClasspath
io.opencensus:opencensus-contrib-http-util:0.31.1=buildScriptClasspath,compileClasspath
io.opencensus:opencensus-proto:0.2.0=buildScriptClasspath
io.perfmark:perfmark-api:0.27.0=buildScriptClasspath
io.perfmark:perfmark-api:0.26.0=buildScriptClasspath
javax.annotation:javax.annotation-api:1.3.2=buildScriptClasspath,compileClasspath
javax.annotation:jsr250-api:1.0=buildScriptClasspath,compileClasspath
javax.inject:javax.inject:1=annotationProcessor,buildScriptClasspath,compileClasspath
org.apache.commons:commons-lang3:3.13.0=buildScriptClasspath,compileClasspath
org.apache.commons:commons-text:1.11.0=buildScriptClasspath,compileClasspath
javax.inject:javax.inject:1=buildScriptClasspath,compileClasspath
org.apache.commons:commons-lang3:3.12.0=buildScriptClasspath,compileClasspath
org.apache.commons:commons-text:1.10.0=buildScriptClasspath,compileClasspath
org.apache.httpcomponents:httpclient:4.5.14=buildScriptClasspath,compileClasspath
org.apache.httpcomponents:httpcore:4.4.16=buildScriptClasspath,compileClasspath
org.checkerframework:checker-qual:3.33.0=annotationProcessor
org.checkerframework:checker-qual:3.42.0=buildScriptClasspath,compileClasspath
org.checkerframework:checker-qual:3.0.0=annotationProcessor
org.checkerframework:checker-qual:3.33.0=buildScriptClasspath,compileClasspath
org.checkerframework:dataflow:3.0.0=annotationProcessor
org.checkerframework:javacutil:3.0.0=annotationProcessor
org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor
org.codehaus.mojo:animal-sniffer-annotations:1.23=buildScriptClasspath
org.conscrypt:conscrypt-openjdk-uber:2.5.2=buildScriptClasspath,compileClasspath
org.json:json:20160212=buildScriptClasspath,compileClasspath
@@ -104,6 +102,9 @@ org.ow2.asm:asm-commons:7.0=buildScriptClasspath,compileClasspath
org.ow2.asm:asm-tree:7.0=buildScriptClasspath,compileClasspath
org.ow2.asm:asm-util:7.0=buildScriptClasspath,compileClasspath
org.ow2.asm:asm:7.0=buildScriptClasspath,compileClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor
org.pcollections:pcollections:2.1.2=annotationProcessor
org.plumelib:plume-util:1.0.6=annotationProcessor
org.plumelib:reflection-util:0.0.2=annotationProcessor
org.plumelib:require-javadoc:0.1.0=annotationProcessor
org.threeten:threetenbp:1.6.8=buildScriptClasspath,compileClasspath
empty=

View File

@@ -35,7 +35,7 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Creates the files for a web-page summary of a given {@link ProjectData}.
* Creates the files for a web-page summary of a given {@Link ProjectData}.
*
* <p>The main job of this class is rendering a tailored cover page that includes information about
* the project and any task that ran.

View File

@@ -16,6 +16,7 @@ package google.registry.gradle.plugin;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier;
import static java.nio.charset.StandardCharsets.UTF_8;

View File

@@ -11,8 +11,8 @@ com.diffplug.spotless:spotless-lib:2.40.0=classpath
com.diffplug.spotless:spotless-plugin-gradle:6.20.0=classpath
com.dorongold.plugins:task-tree:2.1.0=classpath
com.dorongold.task-tree:com.dorongold.task-tree.gradle.plugin:2.1.0=classpath
com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:8.1.1=classpath
com.github.johnrengelman:shadow:8.1.1=classpath
com.github.jengelman.gradle.plugins:shadow:5.1.0=classpath
com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:5.1.0=classpath
com.github.node-gradle.node:com.github.node-gradle.node.gradle.plugin:3.0.1=classpath
com.github.node-gradle:gradle-node-plugin:3.0.1=classpath
com.google.cloud.tools:appengine-gradle-plugin:2.4.1=classpath
@@ -29,34 +29,35 @@ com.googlecode.javaewah:JavaEWAH:1.2.3=classpath
com.squareup.okhttp3:okhttp:4.10.0=classpath
com.squareup.okio:okio-jvm:3.0.0=classpath
com.squareup.okio:okio:3.0.0=classpath
commons-io:commons-io:2.11.0=classpath
commons-io:commons-io:2.6=classpath
dev.equo.ide:solstice:1.3.1=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:3.1.0=classpath
net.ltgt.gradle:gradle-errorprone-plugin:3.1.0=classpath
org.apache.ant:ant-launcher:1.10.13=classpath
org.apache.ant:ant:1.10.13=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:2.0.2=classpath
net.ltgt.gradle:gradle-errorprone-plugin:2.0.2=classpath
org.apache.ant:ant-launcher:1.9.7=classpath
org.apache.ant:ant:1.9.7=classpath
org.apache.commons:commons-compress:1.20=classpath
org.apache.commons:commons-lang3:3.5=classpath
org.checkerframework:checker-qual:2.10.0=classpath
org.codehaus.plexus:plexus-utils:3.5.1=classpath
org.codehaus.plexus:plexus-utils:3.0.24=classpath
org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r=classpath
org.eclipse.platform:org.eclipse.osgi:3.18.300=classpath
org.glassfish:javax.json:1.0.4=classpath
org.jdom:jdom2:2.0.6.1=classpath
org.jdom:jdom2:2.0.6=classpath
org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31=classpath
org.jetbrains.kotlin:kotlin-stdlib:1.6.20=classpath
org.jetbrains:annotations:13.0=classpath
org.ow2.asm:asm-commons:9.4=classpath
org.ow2.asm:asm-tree:9.4=classpath
org.ow2.asm:asm:9.4=classpath
org.ow2.asm:asm-analysis:7.0-beta=classpath
org.ow2.asm:asm-commons:7.0-beta=classpath
org.ow2.asm:asm-tree:7.0-beta=classpath
org.ow2.asm:asm:7.0-beta=classpath
org.slf4j:slf4j-api:1.7.36=classpath
org.sonatype.aether:aether-api:1.13.1=classpath
org.sonatype.aether:aether-impl:1.13.1=classpath
org.sonatype.aether:aether-spi:1.13.1=classpath
org.sonatype.aether:aether-util:1.13.1=classpath
org.tukaani:xz:1.9=classpath
org.vafer:jdependency:2.8.0=classpath
org.vafer:jdependency:2.1.1=classpath
org.yaml:snakeyaml:1.21=classpath
empty=

View File

@@ -57,7 +57,7 @@ dependencies {
implementation deps['com.github.ben-manes.caffeine:caffeine']
implementation deps['com.google.code.findbugs:jsr305']
implementation deps['com.google.guava:guava']
implementation deps['jakarta.inject:jakarta.inject-api']
implementation deps['javax.inject:javax.inject']
implementation deps['joda-time:joda-time']
implementation deps['com.google.flogger:flogger']
implementation deps['io.github.java-diff-utils:java-diff-utils']

View File

@@ -1,68 +1,69 @@
# 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.
aopalliance:aopalliance:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:2.9.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.10.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.auto:auto-common:0.10=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.19.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotations:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_check_api:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_core:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.flogger:flogger:0.7.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
com.google.guava:guava-parent:32.1.2-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:guava:27.0.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:32.1.2-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,testCompileClasspath,testingCompileClasspath
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.truth:truth:1.4.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath,testingCompileClasspath
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.truth:truth:1.1.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.puppycrawl.tools:checkstyle:9.3=checkstyle
commons-beanutils:commons-beanutils:1.9.4=checkstyle
commons-collections:commons-collections:3.2.2=checkstyle
info.picocli:picocli:4.6.2=checkstyle
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
io.github.java-diff-utils:java-diff-utils:4.12=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
javax.inject:javax.inject:1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
joda-time:joda-time:2.12.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
net.sf.saxon:Saxon-HE:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.checkerframework:checker-qual:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.checkerframework:checker-qual:3.42.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.checkerframework:checker-qual:3.35.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.checkerframework:dataflow:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.checkerframework:javacutil:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
org.jacoco:org.jacoco.agent:0.8.9=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.9=jacocoAnt
org.jacoco:org.jacoco.core:0.8.9=jacocoAnt
org.jacoco:org.jacoco.report:0.8.9=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.junit.jupiter:junit-jupiter-api:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.10.0=testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.6=jacocoAnt
org.ow2.asm:asm-tree:9.6=jacocoAnt
org.ow2.asm:asm:9.6=compileClasspath,deploy_jar,jacocoAnt,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.ow2.asm:asm-commons:9.5=jacocoAnt
org.ow2.asm:asm-tree:9.5=jacocoAnt
org.ow2.asm:asm:9.5=compileClasspath,deploy_jar,jacocoAnt,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.pcollections:pcollections:2.1.2=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.plumelib:plume-util:1.0.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.plumelib:reflection-util:0.0.2=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.plumelib:require-javadoc:0.1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.reflections:reflections:0.10.2=checkstyle
empty=testingCompile,testingRuntime,testingRuntimeClasspath
empty=errorproneJavac,testingCompile,testingRuntime,testingRuntimeClasspath

View File

@@ -1,43 +0,0 @@
// Copyright 2023 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.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterators.partition;
import static com.google.common.collect.Iterators.transform;
import static com.google.common.collect.Streams.stream;
import static java.lang.Math.min;
import com.google.common.collect.ImmutableList;
import java.util.stream.Stream;
/** Utilities for breaking up a {@link Stream} into batches. */
public final class BatchedStreams {
static final int MAX_BATCH = 1024 * 1024;
private BatchedStreams() {}
/**
* Transform a flat {@link Stream} into a {@code Stream} of batches.
*
* <p>Closing the returned stream does not close the original stream.
*/
public static <T> Stream<ImmutableList<T>> toBatches(Stream<T> stream, int batchSize) {
checkArgument(batchSize > 0, "batchSize must be a positive integer.");
return stream(
transform(partition(stream.iterator(), min(MAX_BATCH, batchSize)), ImmutableList::copyOf));
}
}

View File

@@ -1,65 +0,0 @@
// Copyright 2023 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.util;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.util.BatchedStreams.toBatches;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableList;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link BatchedStreams}. */
public class BatchedStreamsTest {
@Test
void invalidBatchSize() {
assertThat(assertThrows(IllegalArgumentException.class, () -> toBatches(Stream.of(), 0)))
.hasMessageThat()
.contains("must be a positive integer");
}
@Test
void batch_success() {
// 900_002 elements -> 900 1K-batches + 1 2-element-batch
Stream<Integer> data = IntStream.rangeClosed(0, 900_001).boxed();
assertThat(
toBatches(data, 1000).map(ImmutableList::size).collect(groupingBy(x -> x, counting())))
.containsExactly(1000, 900L, 2, 1L);
}
@Test
void batch_partialBatch() {
Stream<Integer> data = Stream.of(1, 2, 3);
assertThat(
toBatches(data, 1000).map(ImmutableList::size).collect(groupingBy(x -> x, counting())))
.containsExactly(3, 1L);
}
@Test
void batch_truncateBatchSize() {
// 2M elements -> 2 1M-batches despite the user-specified 2M batch size.
Stream<Integer> data = IntStream.range(0, 1024 * 2048).boxed();
assertThat(
toBatches(data, 2_000_000)
.map(ImmutableList::size)
.collect(groupingBy(x -> x, counting())))
.containsExactly(1024 * 1024, 2L);
}
}

View File

@@ -14,6 +14,7 @@
package google.registry.testing;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.flogger.FluentLogger;
@@ -30,26 +31,31 @@ public final class SystemInfo {
private static final LoadingCache<String, Boolean> hasCommandCache =
Caffeine.newBuilder()
.build(
cmd -> {
try {
Process pid = Runtime.getRuntime().exec(cmd.split(" "));
pid.getOutputStream().close();
pid.waitFor();
} catch (IOException e) {
logger.atWarning().withCause(e).log("%s command not available.", cmd);
return false;
new CacheLoader<String, Boolean>() {
@Override
public Boolean load(String cmd) throws InterruptedException {
try {
Process pid = Runtime.getRuntime().exec(cmd);
pid.getOutputStream().close();
pid.waitFor();
} catch (IOException e) {
logger.atWarning().withCause(e).log("%s command not available.", cmd);
return false;
}
return true;
}
return true;
});
/**
* Returns {@code true} if system command can be run from the path.
* Returns {@code true} if system command can be run from path.
*
* <p><b>Warning:</b> The command is actually run! So there could be side effects. You might need
* to specify a version flag or something. Return code is ignored.
* <p><b>Warning:</b> The command is actually run! So there could be side-effects. You might
* need to specify a version flag or something. Return code is ignored.
*
* <p>This result is a memoized. If multiple threads try to get the same result at once, the heavy
* lifting will only be performed by the first thread and the rest will wait.
* <p>This result is a memoized. If multiple therads try to get the same result at once, the
* heavy lifting will only be performed by the first thread and the rest will wait.
*
* @throws ExecutionException
*/
public static boolean hasCommand(String cmd) throws ExecutionException {
return hasCommandCache.get(cmd);

View File

@@ -307,95 +307,6 @@
},
{
"moduleLicense": "The W3C Software License"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleName": "com.squareup.okhttp3:okhttp"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleName": "com.squareup.okio:okio"
},
{
"moduleLicense": "(GPL-2.0-only WITH Classpath-exception-2.0)",
"moduleName": "io.github.eisop:dataflow-errorprone"
},
{
"moduleLicense": "GNU General Public License, version 2 (GPL2), with the classpath exception",
"moduleName": "io.github.eisop:dataflow-errorprone"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "3.0.0",
"moduleName": "com.squareup.okio:okio-bom"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "3.4.0",
"moduleName": "com.squareup.okio:okio-fakefilesystem"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "4.9.3",
"moduleName": "com.squareup.wire:wire-runtime"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "4.8.0",
"moduleName": "com.squareup.wire:wire-schema"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.15.1",
"moduleName": "com.squareup:kotlinpoet"
},
{
"moduleLicense": "Apache License Version 2.0",
"moduleVersion": "3.0.0.M2",
"moduleName": "io.apicurio:apicurio-registry-protobuf-schema-utilities"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.4.0",
"moduleName": "org.jetbrains.kotlin:kotlin-bom"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.9.20",
"moduleName": "org.jetbrains.kotlin:kotlin-stdlib-common"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.5.2",
"moduleName": "org.jetbrains.kotlinx:kotlinx-coroutines-core"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "0.4.0",
"moduleName": "org.jetbrains.kotlinx:kotlinx-datetime"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.0.1",
"moduleName": "org.jetbrains.kotlinx:kotlinx-serialization-core"
},
{
// "Apache License, Version 2.0".
"moduleLicense": null,
"moduleVersion": "1.4",
"moduleName": "jakarta-regexp:jakarta-regexp"
}
]
}

View File

@@ -47,7 +47,7 @@ class GradleFlag:
PROPERTIES_HEADER = """\
# This file defines properties used by the gradle build. It must be kept in
# This file defines properties used by the gradle build. It must be kept in
# sync with config/nom_build.py.
#
# To regenerate, run ./nom_build --generate-gradle-properties
@@ -58,7 +58,6 @@ PROPERTIES_HEADER = """\
# DO NOT EDIT THIS FILE BY HAND
org.gradle.jvmargs=-Xmx1024m
org.gradle.caching=true
org.gradle.parallel=true
"""
# Help text to be displayed (in addition to the synopsis and flag help, which
@@ -100,6 +99,8 @@ PROPERTIES = [
'If true, show all test output in near-realtime.',
'false',
bool),
Property('flowDocsFile',
'Output filename for the flowDocsTool command.'),
Property('enableDependencyLocking',
'Enables dependency locking.',
'true',

View File

@@ -87,11 +87,10 @@ PRESUBMITS = {
PresubmitCheck(
r".*Copyright 20\d{2} The Nomulus Authors\. All Rights Reserved\.",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts"), {
".git", "/build/", "/bin/generated-sources/", "/bin/generated-test-sources/",
".git", "/build/", "/generated/", "/generated_tests/",
"node_modules/", "LoggerConfig.java", "registrar_bin.",
"registrar_dbg.", "google-java-format-diff.py",
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js",
"/src/main/generated", "/src/test/generated"
"nomulus.golden.sql", "soyutils_usegoog.js", "javascript/checks.js"
}, REQUIRED):
"File did not include the license header.",
@@ -172,25 +171,6 @@ PRESUBMITS = {
{"/node_modules/", "google/registry/ui/js/util.js", "registrar_bin."},
):
"JavaScript files should not include console logging.",
PresubmitCheck(
r".*org\.testcontainers\.shaded.*",
"java",
{"/node_modules/"},
):
"Do not use shaded dependencies from testcontainers.",
PresubmitCheck(
r".*com\.google\.common\.truth\.Truth8.*",
"java",
{"/node_modules/"},
):
"Truth8 is deprecated. Use Truth instead.",
PresubmitCheck(
r".*java\.util\.Date.*",
"java",
{"/node_modules/", "JpaTransactionManagerImpl.java"},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
}
# Note that this regex only works for one kind of Flyway file. If we want to

View File

@@ -31,10 +31,7 @@
"style": "kebab-case"
}
],
"eol-last": [
"error",
"always"
]
"eol-last": ["error", "always"]
}
},
{

View File

@@ -1,47 +1,47 @@
# 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.
aopalliance:aopalliance:1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,errorprone,testAnnotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:0.10=annotationProcessor,errorprone,testAnnotationProcessor
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.errorprone:error_prone_check_api:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:guava:27.0.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,errorprone,testAnnotationProcessor
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor,errorprone,testAnnotationProcessor
com.puppycrawl.tools:checkstyle:9.3=checkstyle
commons-beanutils:commons-beanutils:1.9.4=checkstyle
commons-collections:commons-collections:3.2.2=checkstyle
info.picocli:picocli:4.6.2=checkstyle
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
net.sf.saxon:Saxon-HE:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
org.checkerframework:checker-qual:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor
org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
org.checkerframework:dataflow:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
org.checkerframework:javacutil:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,errorprone,testAnnotationProcessor
org.jacoco:org.jacoco.agent:0.8.9=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.9=jacocoAnt
org.jacoco:org.jacoco.core:0.8.9=jacocoAnt
org.jacoco:org.jacoco.report:0.8.9=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.ow2.asm:asm-commons:9.6=jacocoAnt
org.ow2.asm:asm-tree:9.6=jacocoAnt
org.ow2.asm:asm:9.6=jacocoAnt
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor
org.ow2.asm:asm-commons:9.5=jacocoAnt
org.ow2.asm:asm-tree:9.5=jacocoAnt
org.ow2.asm:asm:9.5=jacocoAnt
org.pcollections:pcollections:2.1.2=annotationProcessor,errorprone,testAnnotationProcessor
org.plumelib:plume-util:1.0.6=annotationProcessor,errorprone,testAnnotationProcessor
org.plumelib:reflection-util:0.0.2=annotationProcessor,errorprone,testAnnotationProcessor
org.plumelib:require-javadoc:0.1.0=annotationProcessor,errorprone,testAnnotationProcessor
org.reflections:reflections:0.10.2=checkstyle
empty=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=compileClasspath,deploy_jar,errorproneJavac,runtimeClasspath,testCompileClasspath,testRuntimeClasspath

File diff suppressed because it is too large Load Diff

View File

@@ -16,35 +16,35 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^17.0.7",
"@angular/cdk": "^17.0.4",
"@angular/common": "^17.0.7",
"@angular/compiler": "^17.0.7",
"@angular/core": "^17.0.7",
"@angular/forms": "^17.0.7",
"@angular/material": "^17.0.4",
"@angular/platform-browser": "^17.0.7",
"@angular/platform-browser-dynamic": "^17.0.7",
"@angular/router": "^17.0.7",
"@angular/animations": "^15.2.2",
"@angular/cdk": "^15.2.2",
"@angular/common": "^15.2.2",
"@angular/compiler": "^15.2.2",
"@angular/core": "^15.2.2",
"@angular/forms": "^15.2.2",
"@angular/material": "^15.2.2",
"@angular/platform-browser": "^15.2.2",
"@angular/platform-browser-dynamic": "^15.2.2",
"@angular/router": "^15.2.2",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.0.7",
"@angular-eslint/builder": "17.1.1",
"@angular-eslint/eslint-plugin": "17.1.1",
"@angular-eslint/eslint-plugin-template": "17.1.1",
"@angular-eslint/schematics": "17.1.1",
"@angular-eslint/template-parser": "17.1.1",
"@angular/cli": "~17.0.7",
"@angular/compiler-cli": "^17.0.7",
"@angular-devkit/build-angular": "^15.2.4",
"@angular-eslint/builder": "15.2.1",
"@angular-eslint/eslint-plugin": "15.2.1",
"@angular-eslint/eslint-plugin-template": "15.2.1",
"@angular-eslint/schematics": "15.2.1",
"@angular-eslint/template-parser": "15.2.1",
"@angular/cli": "~15.2.4",
"@angular/compiler-cli": "^15.2.2",
"@types/jasmine": "~4.0.0",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"@typescript-eslint/eslint-plugin": "5.48.2",
"@typescript-eslint/parser": "5.48.2",
"concurrently": "^7.6.0",
"eslint": "^8.39.0",
"eslint": "^8.33.0",
"jasmine-core": "~4.3.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.1.0",
@@ -52,6 +52,6 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.0.0",
"prettier": "2.8.7",
"typescript": "~5.2.2"
"typescript": "~4.9.4"
}
}
}

View File

@@ -17,19 +17,11 @@ import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material.module';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { BackendService } from './shared/services/backend.service';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule,
MaterialModule,
BrowserAnimationsModule,
],
providers: [BackendService],
imports: [RouterTestingModule, MaterialModule, BrowserAnimationsModule],
declarations: [AppComponent],
}).compileComponents();
});

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { AfterViewInit, Component, ViewChild, effect } from '@angular/core';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { RegistrarService } from './registrar/registrar.service';
import { UserDataService } from './shared/services/userData.service';
import { GlobalLoaderService } from './shared/services/globalLoader.service';
@@ -36,13 +36,11 @@ export class AppComponent implements AfterViewInit {
protected globalLoader: GlobalLoaderService,
protected router: Router
) {
effect(() => {
if (registrarService.registrarId()) {
this.renderRouter = false;
setTimeout(() => {
this.renderRouter = true;
}, 400);
}
registrarService.activeRegistrarIdChange.subscribe(() => {
this.renderRouter = false;
setTimeout(() => {
this.renderRouter = true;
}, 400);
});
}

View File

@@ -49,14 +49,15 @@ import { SettingsWidgetComponent } from './home/widgets/settingsWidget.component
import { UserDataService } from './shared/services/userData.service';
import WhoisComponent from './settings/whois/whois.component';
import { SnackBarModule } from './snackbar.module';
import { RegistrarDetailsComponent } from './registrar/registrarDetails.component';
import {
RegistrarDetailsComponent,
RegistrarDetailsWrapperComponent,
} from './registrar/registrarDetails.component';
import { DomainListComponent } from './domains/domainList.component';
import { DialogBottomSheetWrapper } from './shared/components/dialogBottomSheet.component';
@NgModule({
declarations: [
AppComponent,
DialogBottomSheetWrapper,
BillingWidgetComponent,
ContactDetailsDialogComponent,
ContactWidgetComponent,
@@ -69,6 +70,7 @@ import { DialogBottomSheetWrapper } from './shared/components/dialogBottomSheet.
PromotionsWidgetComponent,
RegistrarComponent,
RegistrarDetailsComponent,
RegistrarDetailsWrapperComponent,
RegistrarSelectorComponent,
ResourcesWidgetComponent,
SecurityComponent,

View File

@@ -1,13 +1,7 @@
<div class="console-domains">
<mat-form-field>
<mat-label>Filter</mat-label>
<input
type="search"
matInput
[(ngModel)]="searchTerm"
(ngModelChange)="sendInput()"
#input
/>
<input matInput (keyup)="applyFilter($event)" #input />
</mat-form-field>
<div *ngIf="isLoading; else domains_content" class="console-domains__loading">

View File

@@ -15,10 +15,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DomainListComponent } from './domainList.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MaterialModule } from '../material.module';
import { BackendService } from '../shared/services/backend.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
describe('DomainListComponent', () => {
let component: DomainListComponent;
@@ -27,12 +23,6 @@ describe('DomainListComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [DomainListComponent],
imports: [
HttpClientTestingModule,
MaterialModule,
BrowserAnimationsModule,
],
providers: [BackendService],
}).compileComponents();
fixture = TestBed.createComponent(DomainListComponent);

View File

@@ -18,7 +18,6 @@ import { BackendService } from '../shared/services/backend.service';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { RegistrarService } from '../registrar/registrar.service';
import { Domain, DomainListService } from './domainList.service';
import { Subject, debounceTime } from 'rxjs';
@Component({
selector: 'app-domain-list',
@@ -28,7 +27,6 @@ import { Subject, debounceTime } from 'rxjs';
})
export class DomainListComponent {
public static PATH = 'domain-list';
private readonly DEBOUNCE_MS = 500;
displayedColumns: string[] = [
'domainName',
@@ -40,9 +38,6 @@ export class DomainListComponent {
dataSource: MatTableDataSource<Domain> = new MatTableDataSource();
isLoading = true;
searchTermSubject = new Subject<string>();
searchTerm?: string;
pageNumber?: number;
resultsPerPage = 50;
totalResults?: number;
@@ -57,28 +52,13 @@ export class DomainListComponent {
ngOnInit() {
this.dataSource.paginator = this.paginator;
// Don't spam the server unnecessarily while the user is typing
this.searchTermSubject
.pipe(debounceTime(this.DEBOUNCE_MS))
.subscribe((searchTermValue) => {
this.reloadData();
});
this.reloadData();
}
ngOnDestroy() {
this.searchTermSubject.complete();
}
reloadData() {
this.isLoading = true;
this.domainListService
.retrieveDomains(
this.pageNumber,
this.resultsPerPage,
this.totalResults,
this.searchTerm
)
.retrieveDomains(this.pageNumber, this.resultsPerPage, this.totalResults)
.subscribe((domainListResult) => {
this.dataSource.data = domainListResult.domains;
this.totalResults = domainListResult.totalResults;
@@ -86,8 +66,10 @@ export class DomainListComponent {
});
}
sendInput() {
this.searchTermSubject.next(this.searchTerm!);
/** TODO: the backend will need to accept a filter string. */
applyFilter(event: KeyboardEvent) {
// const filterValue = (event.target as HTMLInputElement).value;
this.reloadData();
}
onPageChange(event: PageEvent) {

View File

@@ -47,17 +47,15 @@ export class DomainListService {
retrieveDomains(
pageNumber?: number,
resultsPerPage?: number,
totalResults?: number,
searchTerm?: string
totalResults?: number
) {
return this.backendService
.getDomains(
this.registrarService.registrarId(),
this.registrarService.activeRegistrarId,
this.checkpointTime,
pageNumber,
resultsPerPage,
totalResults,
searchTerm
totalResults
)
.pipe(
tap((domainListResult: DomainListResult) => {

View File

@@ -18,8 +18,6 @@
text-decoration: none;
}
&__header {
margin-top: 0;
margin-bottom: 10px;
@media (max-width: 599px) {
.mat-toolbar {
padding: 0;

View File

@@ -23,10 +23,8 @@ export class BillingWidgetComponent {
constructor(public registrarService: RegistrarService) {}
public get driveFolderUrl(): string {
if (this.registrarService.registrar()?.driveFolderId) {
return `https://drive.google.com/drive/folders/${
this.registrarService.registrar()?.driveFolderId
}`;
if (this.registrarService?.registrar.driveFolderId) {
return `https://drive.google.com/drive/folders/${this.registrarService?.registrar.driveFolderId}`;
}
return '';
}

View File

@@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, effect } from '@angular/core';
import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { RegistrarService } from './registrar.service';
@@ -23,15 +24,22 @@ import { RegistrarService } from './registrar.service';
styleUrls: ['./emptyRegistrar.component.scss'],
})
export class EmptyRegistrar {
private registrarIdChangeSubscription?: Subscription;
constructor(
private route: ActivatedRoute,
protected registrarService: RegistrarService,
private router: Router
) {
effect(() => {
if (registrarService.registrarId()) {
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
}
});
this.registrarIdChangeSubscription =
registrarService.activeRegistrarIdChange.subscribe((newRegistrarId) => {
if (newRegistrarId) {
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
}
});
}
ngOnDestroy() {
this.registrarIdChangeSubscription?.unsubscribe();
}
}

View File

@@ -15,23 +15,18 @@
import { TestBed } from '@angular/core/testing';
import { RegistrarGuard } from './registrar.guard';
import {
ActivatedRouteSnapshot,
Router,
RouterStateSnapshot,
} from '@angular/router';
import { Router, RouterStateSnapshot } from '@angular/router';
import { RegistrarService } from './registrar.service';
describe('RegistrarGuard', () => {
let guard: RegistrarGuard;
let dummyRegistrarService: RegistrarService;
let routeSpy: Router;
let dummyRoute: RouterStateSnapshot;
let dummyRoute: RouterStateSnapshot = {} as RouterStateSnapshot;
beforeEach(() => {
routeSpy = jasmine.createSpyObj<Router>('Router', ['navigate']);
dummyRegistrarService = { activeRegistrarId: '' } as RegistrarService;
dummyRoute = { url: '/value' } as RouterStateSnapshot;
TestBed.configureTestingModule({
providers: [
@@ -44,7 +39,7 @@ describe('RegistrarGuard', () => {
it('should not be able to activate when activeRegistrarId is empty', () => {
guard = TestBed.inject(RegistrarGuard);
const res = guard.canActivate(new ActivatedRouteSnapshot(), dummyRoute);
const res = guard.canActivate();
expect(res).toBeFalsy();
});
@@ -53,16 +48,17 @@ describe('RegistrarGuard', () => {
useValue: { activeRegistrarId: 'value' },
});
guard = TestBed.inject(RegistrarGuard);
const res = guard.canActivate(new ActivatedRouteSnapshot(), dummyRoute);
const res = guard.canActivate();
expect(res).toBeTrue();
});
it('should navigate to empty-registrar screen when activeRegistrarId is empty', () => {
it('should navigate to registrars when activeRegistrarId is empty', () => {
const dummyRoute = { url: '/value' } as RouterStateSnapshot;
guard = TestBed.inject(RegistrarGuard);
guard.canActivate(new ActivatedRouteSnapshot(), dummyRoute);
guard.canActivate();
expect(routeSpy.navigate).toHaveBeenCalledOnceWith([
'/empty-registrar',
{ nextUrl: dummyRoute.url },
'/registrars',
{ nextUrl: '/value' },
]);
});
});

View File

@@ -34,7 +34,7 @@ export class RegistrarGuard {
_: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean> | boolean {
if (this.registrarService.registrarId()) {
if (this.registrarService.activeRegistrarId) {
return true;
}
return this.router.navigate([

View File

@@ -17,7 +17,6 @@ import { TestBed } from '@angular/core/testing';
import { RegistrarService } from './registrar.service';
import { BackendService } from '../shared/services/backend.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MatSnackBar } from '@angular/material/snack-bar';
describe('RegistrarService', () => {
let service: RegistrarService;
@@ -25,7 +24,7 @@ describe('RegistrarService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [BackendService, MatSnackBar],
providers: [BackendService],
});
service = TestBed.inject(RegistrarService);
});

View File

@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable, computed, signal } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { Injectable } from '@angular/core';
import { Observable, Subject, tap } from 'rxjs';
import { BackendService } from '../shared/services/backend.service';
import {
@@ -52,11 +52,9 @@ export interface Registrar {
providedIn: 'root',
})
export class RegistrarService implements GlobalLoader {
registrarId = signal<string>('');
registrars = signal<Registrar[]>([]);
registrar = computed<Registrar | undefined>(() =>
this.registrars().find((r) => r.registrarId === this.registrarId())
);
activeRegistrarId: string = '';
registrars: Registrar[] = [];
activeRegistrarIdChange: Subject<string> = new Subject<string>();
constructor(
private backend: BackendService,
@@ -69,15 +67,22 @@ export class RegistrarService implements GlobalLoader {
this.globalLoader.startGlobalLoader(this);
}
public get registrar(): Registrar {
return this.registrars.filter(
(r) => r.registrarId === this.activeRegistrarId
)[0];
}
public updateSelectedRegistrar(registrarId: string) {
this.registrarId.set(registrarId);
this.activeRegistrarId = registrarId;
this.activeRegistrarIdChange.next(registrarId);
}
public loadRegistrars(): Observable<Registrar[]> {
return this.backend.getRegistrars().pipe(
tap((registrars) => {
if (registrars) {
this.registrars.set(registrars);
this.registrars = registrars;
}
})
);

View File

@@ -1,7 +1,7 @@
<div class="registrarDetails" *ngIf="registrarInEdit">
<div class="registrarDetails">
<h3 mat-dialog-title>Edit Registrar: {{ registrarInEdit.registrarId }}</h3>
<div mat-dialog-content>
<form (ngSubmit)="saveAndClose()">
<form (ngSubmit)="saveAndClose($event)">
<mat-form-field class="registrarDetails__input">
<mat-label>Registry Lock:</mat-label>
<mat-select
@@ -32,7 +32,7 @@
/>
</mat-form-field>
<mat-dialog-actions>
<button mat-button (click)="this.params?.close()">Cancel</button>
<button mat-button (click)="onCancel($event)">Cancel</button>
<button type="submit" mat-button color="primary">Save</button>
</mat-dialog-actions>
</form>

View File

@@ -12,38 +12,61 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component } from '@angular/core';
import { Component, Injector } from '@angular/core';
import { Registrar, RegistrarService } from './registrar.service';
import { BreakpointObserver } from '@angular/cdk/layout';
import {
MAT_BOTTOM_SHEET_DATA,
MatBottomSheet,
MatBottomSheetRef,
} from '@angular/material/bottom-sheet';
import {
MAT_DIALOG_DATA,
MatDialog,
MatDialogRef,
} from '@angular/material/dialog';
import { MatChipInputEvent } from '@angular/material/chips';
import { DialogBottomSheetContent } from '../shared/components/dialogBottomSheet.component';
type RegistrarDetailsParams = {
close: Function;
data: {
registrar: Registrar;
};
};
const MOBILE_LAYOUT_BREAKPOINT = '(max-width: 599px)';
@Component({
selector: 'app-registrar-details',
templateUrl: './registrarDetails.component.html',
styleUrls: ['./registrarDetails.component.scss'],
})
export class RegistrarDetailsComponent implements DialogBottomSheetContent {
export class RegistrarDetailsComponent {
registrarInEdit!: Registrar;
params?: RegistrarDetailsParams;
private elementRef:
| MatBottomSheetRef<RegistrarDetailsComponent>
| MatDialogRef<RegistrarDetailsComponent>;
constructor(protected registrarService: RegistrarService) {}
init(params: RegistrarDetailsParams) {
this.params = params;
this.registrarInEdit = JSON.parse(
JSON.stringify(this.params.data.registrar)
);
constructor(
protected registrarService: RegistrarService,
private injector: Injector
) {
// We only inject one, either Dialog or Bottom Sheet data
// so one of the injectors is expected to fail
try {
var params = this.injector.get(MAT_DIALOG_DATA);
this.elementRef = this.injector.get(MatDialogRef);
} catch (e) {
var params = this.injector.get(MAT_BOTTOM_SHEET_DATA);
this.elementRef = this.injector.get(MatBottomSheetRef);
}
this.registrarInEdit = JSON.parse(JSON.stringify(params.registrar));
}
saveAndClose() {
this.params?.close();
onCancel(e: MouseEvent) {
if (this.elementRef instanceof MatBottomSheetRef) {
this.elementRef.dismiss();
} else if (this.elementRef instanceof MatDialogRef) {
this.elementRef.close();
}
}
saveAndClose(e: MouseEvent) {
// TODO: Implement save call to API
this.onCancel(e);
}
addTLD(e: MatChipInputEvent) {
@@ -59,3 +82,24 @@ export class RegistrarDetailsComponent implements DialogBottomSheetContent {
);
}
}
@Component({
selector: 'app-registrar-details-wrapper',
template: '',
})
export class RegistrarDetailsWrapperComponent {
constructor(
private dialog: MatDialog,
private bottomSheet: MatBottomSheet,
protected breakpointObserver: BreakpointObserver
) {}
open(registrar: Registrar) {
const config = { data: { registrar } };
if (this.breakpointObserver.isMatched(MOBILE_LAYOUT_BREAKPOINT)) {
this.bottomSheet.open(RegistrarDetailsComponent, config);
} else {
this.dialog.open(RegistrarDetailsComponent, config);
}
}
}

View File

@@ -5,20 +5,20 @@
routerLinkActive="active"
*ngIf="isMobile; else desktop"
>
{{ registrarService.registrarId() || "Select registrar" }}
{{ registrarService.activeRegistrarId || "Select registrar" }}
<mat-icon>open_in_new</mat-icon>
</button>
<ng-template #desktop>
<mat-form-field class="mat-form-field-density-5" appearance="fill">
<mat-label>Registrar</mat-label>
<mat-select
[ngModel]="registrarService.registrarId()"
[ngModel]="registrarService.activeRegistrarId"
(selectionChange)="
registrarService.updateSelectedRegistrar($event.value)
"
>
<mat-option
*ngFor="let registrar of registrarService.registrars()"
*ngFor="let registrar of registrarService.registrars"
[value]="registrar.registrarId"
>
{{ registrar.registrarId }}

View File

@@ -15,10 +15,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RegistrarSelectorComponent } from './registrarSelector.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MaterialModule } from '../material.module';
import { BackendService } from '../shared/services/backend.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
describe('RegistrarSelectorComponent', () => {
let component: RegistrarSelectorComponent;
@@ -26,12 +22,6 @@ describe('RegistrarSelectorComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
MaterialModule,
BrowserAnimationsModule,
],
providers: [BackendService],
declarations: [RegistrarSelectorComponent],
}).compileComponents();

View File

@@ -48,7 +48,7 @@
[pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons
></mat-paginator>
<app-dialog-bottom-sheet-wrapper
<app-registrar-details-wrapper
#registrarDetailsView
></app-dialog-bottom-sheet-wrapper>
></app-registrar-details-wrapper>
</div>

View File

@@ -17,8 +17,7 @@ import { Registrar, RegistrarService } from './registrar.service';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { RegistrarDetailsComponent } from './registrarDetails.component';
import { DialogBottomSheetWrapper } from '../shared/components/dialogBottomSheet.component';
import { RegistrarDetailsWrapperComponent } from './registrarDetails.component';
@Component({
selector: 'app-registrar',
@@ -83,11 +82,11 @@ export class RegistrarComponent {
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild('registrarDetailsView')
detailsComponentWrapper!: DialogBottomSheetWrapper;
detailsComponentWrapper!: RegistrarDetailsWrapperComponent;
constructor(protected registrarService: RegistrarService) {
this.dataSource = new MatTableDataSource<Registrar>(
registrarService.registrars()
registrarService.registrars
);
}
@@ -98,10 +97,7 @@ export class RegistrarComponent {
openDetails(event: MouseEvent, registrar: Registrar) {
event.stopPropagation();
this.detailsComponentWrapper.open<RegistrarDetailsComponent>(
RegistrarDetailsComponent,
{ registrar }
);
this.detailsComponentWrapper.open(registrar);
}
applyFilter(event: Event) {

View File

@@ -1,48 +1,44 @@
@if (loading) {
<div class="contact__loading">
<div *ngIf="loading" class="contact__loading">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
} @else {
<div>
@if (contactService.contacts().length === 0) {
<div class="contact__empty-contacts">
<div *ngIf="!loading">
<div
class="contact__empty-contacts"
*ngIf="contactService.contacts.length === 0"
>
<mat-icon class="contact__empty-contacts-icon secondary-text"
>apps_outage</mat-icon
>
<h1>No contacts found</h1>
</div>
} @else { @for (group of groupedContacts(); track group.emailAddress) {
<div class="contact__cards-wrapper">
<h3>{{ group.label }}s</h3>
<mat-divider></mat-divider>
<div class="contact__cards">
<mat-card class="contact__card" *ngFor="let contact of group.contacts">
<mat-card-title>{{ contact.name }}</mat-card-title>
<p *ngIf="contact.phoneNumber">{{ contact.phoneNumber }}</p>
<p *ngIf="contact.emailAddress">{{ contact.emailAddress }}</p>
<mat-card-actions class="contact__card-actions">
<button
mat-button
color="primary"
(click)="openDetails($event, contact)"
>
<mat-icon>edit</mat-icon>Edit
</button>
<button mat-button color="accent" (click)="deleteContact(contact)">
<mat-icon>delete</mat-icon>Delete
</button>
</mat-card-actions>
</mat-card>
<div *ngFor="let group of groupedData">
<div class="contact__cards-wrapper" *ngIf="group.contacts.length">
<h3>{{ group.label }}s</h3>
<mat-divider></mat-divider>
<div class="contact__cards">
<mat-card class="contact__card" *ngFor="let contact of group.contacts">
<mat-card-title>{{ contact.name }}</mat-card-title>
<p *ngIf="contact.phoneNumber">{{ contact.phoneNumber }}</p>
<p *ngIf="contact.emailAddress">{{ contact.emailAddress }}</p>
<mat-card-actions class="contact__card-actions">
<button
mat-button
color="primary"
(click)="openDetails($event, contact)"
>
<mat-icon>edit</mat-icon>Edit
</button>
<button mat-button color="accent" (click)="deleteContact(contact)">
<mat-icon>delete</mat-icon>Delete
</button>
</mat-card-actions>
</mat-card>
</div>
</div>
</div>
} }
<div class="contact__actions">
<button mat-raised-button color="primary" (click)="openCreateNew($event)">
<mat-icon>add</mat-icon>Create a Contact
</button>
</div>
<app-dialog-bottom-sheet-wrapper
#contactDetailsWrapper
></app-dialog-bottom-sheet-wrapper>
</div>
}

View File

@@ -12,14 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild, computed } from '@angular/core';
import { Component, Inject } from '@angular/core';
import {
MatDialog,
MAT_DIALOG_DATA,
MatDialogRef,
} from '@angular/material/dialog';
import {
MatBottomSheet,
MAT_BOTTOM_SHEET_DATA,
MatBottomSheetRef,
} from '@angular/material/bottom-sheet';
import { Contact, ContactService } from './contact.service';
import { BreakpointObserver } from '@angular/cdk/layout';
import { HttpErrorResponse } from '@angular/common/http';
import { MatSnackBar } from '@angular/material/snack-bar';
import {
DialogBottomSheetContent,
DialogBottomSheetWrapper,
} from 'src/app/shared/components/dialogBottomSheet.component';
enum Operations {
DELETE,
@@ -33,13 +40,7 @@ interface GroupedContacts {
contacts: Array<Contact>;
}
type ContactDetailsParams = {
close: Function;
data: {
contact: Contact;
operation: Operations;
};
};
let isMobile: boolean;
const contactTypes: Array<GroupedContacts> = [
{ value: 'ADMIN', label: 'Primary contact', contacts: [] },
@@ -51,46 +52,72 @@ const contactTypes: Array<GroupedContacts> = [
{ value: 'WHOIS', label: 'WHOIS-Inquiry contact', contacts: [] },
];
class ContactDetailsEventsResponder {
private ref?: MatDialogRef<any> | MatBottomSheetRef;
constructor() {
this.onClose = this.onClose.bind(this);
}
setRef(ref: MatDialogRef<any> | MatBottomSheetRef) {
this.ref = ref;
}
onClose() {
if (this.ref == undefined) {
throw "Reference to ContactDetailsDialogComponent hasn't been set. ";
}
if (this.ref instanceof MatBottomSheetRef) {
this.ref.dismiss();
} else if (this.ref instanceof MatDialogRef) {
this.ref.close();
}
}
}
@Component({
selector: 'app-contact-details-dialog',
templateUrl: 'contactDetails.component.html',
styleUrls: ['./contact.component.scss'],
})
export class ContactDetailsDialogComponent implements DialogBottomSheetContent {
contact?: Contact;
export class ContactDetailsDialogComponent {
contact: Contact;
contactTypes = contactTypes;
contactIndex?: number;
params?: ContactDetailsParams;
operation: Operations;
contactIndex: number;
onCloseCallback: Function;
constructor(
public contactService: ContactService,
private _snackBar: MatSnackBar
) {}
init(params: ContactDetailsParams) {
this.params = params;
this.contactIndex = this.contactService
.contacts()
.findIndex((c) => c === params.data.contact);
this.contact = JSON.parse(JSON.stringify(params.data.contact));
private _snackBar: MatSnackBar,
@Inject(isMobile ? MAT_BOTTOM_SHEET_DATA : MAT_DIALOG_DATA)
public data: {
onClose: Function;
contact: Contact;
operation: Operations;
}
) {
this.onCloseCallback = data.onClose;
this.contactIndex = contactService.contacts.findIndex(
(c) => c === data.contact
);
this.contact = JSON.parse(JSON.stringify(data.contact));
this.operation = data.operation;
}
close() {
this.params?.close();
onClose(e: MouseEvent) {
e.preventDefault();
this.onCloseCallback.call(this);
}
saveAndClose(e: SubmitEvent) {
e.preventDefault();
if (!this.contact || this.contactIndex === undefined) return;
if (!(e.target as HTMLFormElement).checkValidity()) {
return;
}
const operation = this.params?.data.operation;
let operationObservable;
if (operation === Operations.ADD) {
if (this.operation === Operations.ADD) {
operationObservable = this.contactService.addContact(this.contact);
} else if (operation === Operations.UPDATE) {
} else if (this.operation === Operations.UPDATE) {
operationObservable = this.contactService.updateContact(
this.contactIndex,
this.contact
@@ -100,7 +127,7 @@ export class ContactDetailsDialogComponent implements DialogBottomSheetContent {
}
operationObservable.subscribe({
complete: () => this.close(),
complete: this.onCloseCallback.bind(this),
error: (err: HttpErrorResponse) => {
this._snackBar.open(err.error);
},
@@ -115,22 +142,12 @@ export class ContactDetailsDialogComponent implements DialogBottomSheetContent {
})
export default class ContactComponent {
public static PATH = 'contact';
public groupedContacts = computed(() => {
return this.contactService.contacts().reduce((acc, contact) => {
contact.types.forEach((contactType) => {
acc
.find((group: GroupedContacts) => group.value === contactType)
?.contacts.push(contact);
});
return acc;
}, JSON.parse(JSON.stringify(contactTypes)));
});
@ViewChild('contactDetailsWrapper')
detailsComponentWrapper!: DialogBottomSheetWrapper;
loading: boolean = false;
constructor(
private dialog: MatDialog,
private bottomSheet: MatBottomSheet,
private breakpointObserver: BreakpointObserver,
public contactService: ContactService,
private _snackBar: MatSnackBar
) {
@@ -141,6 +158,17 @@ export default class ContactComponent {
});
}
public get groupedData() {
return this.contactService.contacts?.reduce((acc, contact) => {
contact.types.forEach((type) => {
acc
.find((group: GroupedContacts) => group.value === type)
?.contacts.push(contact);
});
return acc;
}, JSON.parse(JSON.stringify(contactTypes)));
}
deleteContact(contact: Contact) {
if (confirm(`Please confirm contact ${contact.name} delete`)) {
this.contactService.deleteContact(contact).subscribe({
@@ -167,9 +195,20 @@ export default class ContactComponent {
operation: Operations = Operations.UPDATE
) {
e.preventDefault();
this.detailsComponentWrapper.open<ContactDetailsDialogComponent>(
ContactDetailsDialogComponent,
{ contact, operation }
);
// TODO: handle orientation change
isMobile = this.breakpointObserver.isMatched('(max-width: 599px)');
const responder = new ContactDetailsEventsResponder();
const config = { data: { onClose: responder.onClose, contact, operation } };
if (isMobile) {
const bottomSheetRef = this.bottomSheet.open(
ContactDetailsDialogComponent,
config
);
responder.setRef(bottomSheetRef);
} else {
const dialogRef = this.dialog.open(ContactDetailsDialogComponent, config);
responder.setRef(dialogRef);
}
}
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable, signal } from '@angular/core';
import { Injectable } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { RegistrarService } from 'src/app/registrar/registrar.service';
import { BackendService } from 'src/app/shared/services/backend.service';
@@ -33,7 +33,7 @@ export interface Contact {
providedIn: 'root',
})
export class ContactService {
contacts = signal<Contact[]>([]);
contacts: Contact[] = [];
constructor(
private backend: BackendService,
@@ -42,37 +42,39 @@ export class ContactService {
// TODO: Come up with a better handling for registrarId
fetchContacts(): Observable<Contact[]> {
return this.backend.getContacts(this.registrarService.registrarId()).pipe(
tap((contacts = []) => {
this.contacts.set(contacts);
})
);
return this.backend
.getContacts(this.registrarService.activeRegistrarId)
.pipe(
tap((contacts) => {
this.contacts = contacts;
})
);
}
saveContacts(contacts: Contact[]): Observable<Contact[]> {
return this.backend
.postContacts(this.registrarService.registrarId(), contacts)
.postContacts(this.registrarService.activeRegistrarId, contacts)
.pipe(
tap((_) => {
this.contacts.set(contacts);
this.contacts = contacts;
})
);
}
updateContact(index: number, contact: Contact) {
const newContacts = this.contacts().map((c, i) =>
const newContacts = this.contacts.map((c, i) =>
i === index ? contact : c
);
return this.saveContacts(newContacts);
}
addContact(contact: Contact) {
const newContacts = this.contacts().concat([contact]);
const newContacts = this.contacts.concat([contact]);
return this.saveContacts(newContacts);
}
deleteContact(contact: Contact) {
const newContacts = this.contacts().filter((c) => c !== contact);
const newContacts = this.contacts.filter((c) => c !== contact);
return this.saveContacts(newContacts);
}
}

View File

@@ -1,5 +1,5 @@
<h3 mat-dialog-title>Contact details</h3>
<div mat-dialog-content *ngIf="contact">
<div mat-dialog-content>
<form (ngSubmit)="saveAndClose($event)">
<p>
<mat-form-field class="contact-details__input">
@@ -97,7 +97,7 @@
>
</section>
<mat-dialog-actions>
<button mat-button (click)="close()">Cancel</button>
<button mat-button (click)="onClose($event)">Cancel</button>
<button type="submit" mat-button>Save</button>
</mat-dialog-actions>
</form>

View File

@@ -15,24 +15,19 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import SecurityComponent from './security.component';
import { SecurityService, apiToUiConverter } from './security.service';
import { SecurityService } from './security.service';
import { BackendService } from 'src/app/shared/services/backend.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MaterialModule } from 'src/app/material.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { FormsModule } from '@angular/forms';
import {
Registrar,
RegistrarService,
} from 'src/app/registrar/registrar.service';
describe('SecurityComponent', () => {
let component: SecurityComponent;
let fixture: ComponentFixture<SecurityComponent>;
let fetchSecurityDetailsSpy: Function;
let saveSpy: Function;
let dummyRegistrarService: RegistrarService;
beforeEach(async () => {
const securityServiceSpy = jasmine.createSpyObj(SecurityService, [
@@ -45,9 +40,9 @@ describe('SecurityComponent', () => {
saveSpy = securityServiceSpy.saveChanges;
dummyRegistrarService = {
registrar: { ipAddressAllowList: ['123.123.123.123'] },
} as RegistrarService;
securityServiceSpy.securitySettings = {
ipAddressAllowList: [{ value: '123.123.123.123' }],
};
await TestBed.configureTestingModule({
imports: [
@@ -57,10 +52,7 @@ describe('SecurityComponent', () => {
FormsModule,
],
declarations: [SecurityComponent],
providers: [
BackendService,
{ provide: RegistrarService, useValue: dummyRegistrarService },
],
providers: [BackendService],
})
.overrideComponent(SecurityComponent, {
set: {
@@ -80,6 +72,10 @@ describe('SecurityComponent', () => {
expect(component).toBeTruthy();
});
it('should call fetch spy', () => {
expect(fetchSecurityDetailsSpy).toHaveBeenCalledTimes(1);
});
it('should render ip allow list', waitForAsync(() => {
component.enableEdit();
fixture.whenStable().then(() => {
@@ -125,17 +121,16 @@ describe('SecurityComponent', () => {
});
it('should create temporary data structure', () => {
expect(component.dataSource).toEqual(
apiToUiConverter(dummyRegistrarService.registrar)
expect(component.dataSource).toBe(
component.securityService.securitySettings
);
component.enableEdit();
expect(component.dataSource).not.toBe(
component.securityService.securitySettings
);
component.removeIpEntry(0);
expect(component.dataSource).toEqual({ ipAddressAllowList: [] });
expect(dummyRegistrarService.registrar).toEqual({
ipAddressAllowList: ['123.123.123.123'],
} as Registrar);
component.cancel();
expect(component.dataSource).toEqual(
apiToUiConverter(dummyRegistrarService.registrar)
expect(component.dataSource).toBe(
component.securityService.securitySettings
);
});

View File

@@ -40,7 +40,7 @@ export default class SecurityComponent {
private _snackBar: MatSnackBar,
public registrarService: RegistrarService
) {
this.dataSource = apiToUiConverter(this.registrarService.registrar());
this.dataSource = apiToUiConverter(this.registrarService.registrar);
}
enableEdit() {
@@ -76,6 +76,6 @@ export default class SecurityComponent {
}
resetDataSource() {
this.dataSource = apiToUiConverter(this.registrarService.registrar());
this.dataSource = apiToUiConverter(this.registrarService.registrar);
}
}

View File

@@ -24,7 +24,6 @@ import {
import { HttpClientTestingModule } from '@angular/common/http/testing';
import SecurityComponent from './security.component';
import { BackendService } from 'src/app/shared/services/backend.service';
import { MatSnackBar } from '@angular/material/snack-bar';
describe('SecurityService', () => {
const uiMockData: SecuritySettings = {
@@ -44,7 +43,7 @@ describe('SecurityService', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [SecurityComponent],
providers: [MatSnackBar, SecurityService, BackendService],
providers: [SecurityService, BackendService],
});
service = TestBed.inject(SecurityService);
});

View File

@@ -64,7 +64,7 @@ export class SecurityService {
saveChanges(newSecuritySettings: SecuritySettings) {
return this.backend
.postSecuritySettings(
this.registrarService.registrarId(),
this.registrarService.activeRegistrarId,
uiToApiConverter(newSecuritySettings)
)
.pipe(

View File

@@ -133,8 +133,9 @@
<h3>Address Line 1:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress?.street">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress?.street"
matInput
type="text"
[(ngModel)]="(registrar.localizedAddress?.street)![0]"
@@ -148,8 +149,9 @@
<h3>City:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress"
matInput
type="text"
[(ngModel)]="registrar.localizedAddress.city"
@@ -165,8 +167,9 @@
<h3>Address Line 2:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress?.street">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress?.street"
matInput
type="text"
[(ngModel)]="(registrar.localizedAddress?.street)![1]"
@@ -180,8 +183,9 @@
<h3>State/Region:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress"
matInput
type="text"
[(ngModel)]="registrar.localizedAddress.state"
@@ -197,8 +201,9 @@
<h3>Address Line 3:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress?.street">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress?.street"
matInput
type="text"
[(ngModel)]="(registrar.localizedAddress?.street)![2]"
@@ -212,8 +217,9 @@
<h3>Country Code:</h3>
</div>
<div class="settings-whois__section-form">
<mat-form-field *ngIf="registrar.localizedAddress">
<mat-form-field>
<input
*ngIf="registrar.localizedAddress"
matInput
type="text"
[(ngModel)]="registrar.localizedAddress.countryCode"

View File

@@ -15,11 +15,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import WhoisComponent from './whois.component';
import { MaterialModule } from 'src/app/material.module';
import { BackendService } from 'src/app/shared/services/backend.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RegistrarService } from 'src/app/registrar/registrar.service';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
describe('WhoisComponent', () => {
let component: WhoisComponent;
@@ -28,15 +23,6 @@ describe('WhoisComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [WhoisComponent],
imports: [
HttpClientTestingModule,
MaterialModule,
BrowserAnimationsModule,
],
providers: [
BackendService,
{ provide: RegistrarService, useValue: { registrar: {} } },
],
}).compileComponents();
fixture = TestBed.createComponent(WhoisComponent);

View File

@@ -1,69 +0,0 @@
// Copyright 2023 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.
import { BreakpointObserver } from '@angular/cdk/layout';
import { ComponentType } from '@angular/cdk/portal';
import { Component } from '@angular/core';
import {
MatBottomSheet,
MatBottomSheetRef,
} from '@angular/material/bottom-sheet';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
const MOBILE_LAYOUT_BREAKPOINT = '(max-width: 599px)';
export interface DialogBottomSheetContent {
init(data: Object): void;
}
/**
* Wraps up a child component in an Angular Material Dalog for desktop or a Bottom Sheet
* component for mobile depending on a screen resolution, with Breaking Point being 599px.
* Child component is required to implement @see DialogBottomSheetContent interface
*/
@Component({
selector: 'app-dialog-bottom-sheet-wrapper',
template: '',
})
export class DialogBottomSheetWrapper {
private elementRef?: MatBottomSheetRef | MatDialogRef<any>;
constructor(
private dialog: MatDialog,
private bottomSheet: MatBottomSheet,
protected breakpointObserver: BreakpointObserver
) {}
open<T extends DialogBottomSheetContent>(
component: ComponentType<T>,
data: any
) {
const config = { data, close: () => this.close() };
if (this.breakpointObserver.isMatched(MOBILE_LAYOUT_BREAKPOINT)) {
this.elementRef = this.bottomSheet.open(component);
this.elementRef.instance.init(config);
} else {
this.elementRef = this.dialog.open(component);
this.elementRef.componentInstance.init(config);
}
}
close() {
if (this.elementRef instanceof MatBottomSheetRef) {
this.elementRef.dismiss();
} else if (this.elementRef instanceof MatDialogRef) {
this.elementRef.close();
}
}
}

View File

@@ -69,8 +69,7 @@ export class BackendService {
checkpointTime?: string,
pageNumber?: number,
resultsPerPage?: number,
totalResults?: number,
searchTerm?: string
totalResults?: number
): Observable<DomainListResult> {
var url = `/console-api/domain-list?registrarId=${registrarId}`;
if (checkpointTime) {
@@ -85,9 +84,6 @@ export class BackendService {
if (totalResults) {
url += `&totalResults=${totalResults}`;
}
if (searchTerm) {
url += `&searchTerm=${searchTerm}`;
}
return this.http
.get<DomainListResult>(url)
.pipe(catchError((err) => this.errorCatcher<DomainListResult>(err)));

View File

@@ -35,6 +35,15 @@ $theme-warn: mat.define-palette(mat.$red-palette);
@include form-field-density(-5);
}
@import "@angular/material/theming";
// Define application specific typography settings, font-family, etc
$typography-configuration: mat-typography-config(
$font-family: 'Roboto, "Helvetica Neue", sans-serif',
);
@include angular-material-typography($typography-configuration);
/**
** Light theme
**/

View File

@@ -1,3 +1,3 @@
FROM eclipse-temurin:21
FROM gcr.io/distroless/java:debug
ADD build/libs/nomulus.jar /nomulus.jar
ENTRYPOINT ["java", "-jar", "/nomulus.jar"]
ENTRYPOINT ["/usr/bin/java", "-jar", "/nomulus.jar"]

View File

@@ -31,6 +31,20 @@ def goldensDir =
"${javaTestDir}/google/registry/webdriver/goldens/chrome-linux"
def jsDir = "${project.projectDir}/src/main/javascript"
// Tests that conflict with (mostly unidentified) members of the main test
// suite. It is unclear if they are offenders (i.e., those that pollute global
// state) or victims.
// TODO(weiminyu): identify cause and fix offending tests.
def outcastTestPatterns = [
// Problem seems to lie with AppEngine TaskQueue for test.
"google/registry/batch/RefreshDnsOnHostRenameActionTest.*",
"google/registry/flows/CheckApiActionTest.*",
"google/registry/flows/EppLifecycleHostTest.*",
"google/registry/flows/domain/DomainCreateFlowTest.*",
"google/registry/flows/domain/DomainUpdateFlowTest.*",
"google/registry/tools/CreateDomainCommandTest.*",
]
// Tests that fail when running Gradle in a docker container, e. g. when
// building the release artifacts in Google Cloud Build.
def dockerIncompatibleTestPatterns = [
@@ -49,9 +63,9 @@ def dockerIncompatibleTestPatterns = [
"google/registry/persistence/PersistenceModuleTest.*",
]
// Tests that conflict with members of the main test suite. They seem to be
// affected by global states outside of Nomulus classes, e.g., threads and
// objects retained by frameworks.
// Tests that conflict with members of both the main test suite and the
// outcast suite. They seem to be affected by global states outside of
// Nomulus classes, e.g., threads and objects retained by frameworks.
// TODO(weiminyu): identify cause and fix offending tests.
def fragileTestPatterns = [
// Changes cache timeouts and for some reason appears to have contention
@@ -85,6 +99,12 @@ sourceSets {
java {
compileClasspath += nonprod.output
runtimeClasspath += nonprod.output
// Javadoc API is deprecated in Java 11 and removed in Java 12.
// TODO(jianglai): re-enable after migrating to the new Javadoc API
if ((JavaVersion.current().majorVersion as Integer) >= 11) {
exclude 'google/registry/documentation/**'
}
}
resources {
exclude '**/*.xjb', '**/*.xsd'
@@ -104,8 +124,10 @@ configurations {
devtool
nonprodImplementation.extendsFrom implementation
nonprodRuntime.extendsFrom runtime
testImplementation.extendsFrom nonprodImplementation
testRuntimeOnly.extendsFrom nonprodRuntime
// Published jars that are used for server/schema compatibility tests.
// See <a href="../integration/README.md">the integration project</a>
@@ -166,6 +188,7 @@ dependencies {
implementation deps['com.google.dagger:dagger']
implementation deps['com.google.errorprone:error_prone_annotations']
implementation deps['com.google.flogger:flogger']
runtime deps['com.google.flogger:flogger-system-backend']
implementation deps['com.google.guava:guava']
implementation deps['com.google.protobuf:protobuf-java']
// Might need to add this back if we re-add nebula-lint
@@ -188,14 +211,16 @@ dependencies {
implementation deps['com.google.template:soy']
implementation deps['com.googlecode.json-simple:json-simple']
implementation deps['com.jcraft:jsch']
testImplementation deps['com.thoughtworks.qdox:qdox']
implementation deps['com.zaxxer:HikariCP']
implementation deps['com.squareup.okhttp3:okhttp']
implementation deps['dnsjava:dnsjava']
testRuntimeOnly deps['guru.nidi:graphviz-java-all-j2v8']
runtime deps['guru.nidi:graphviz-java-all-j2v8']
testImplementation deps['io.github.classgraph:classgraph']
testRuntimeOnly deps['io.github.java-diff-utils:java-diff-utils']
testImplementation deps['javax.annotation:javax.annotation-api']
testImplementation deps['javax.annotation:jsr250-api']
implementation deps['javax.mail:mail']
implementation deps['jakarta.inject:jakarta.inject-api']
implementation deps['javax.inject:javax.inject']
implementation deps['javax.persistence:javax.persistence-api']
implementation deps['javax.servlet:servlet-api']
implementation deps['javax.xml.bind:jaxb-api']
@@ -219,10 +244,11 @@ dependencies {
testImplementation deps['org.apache.sshd:sshd-scp']
testImplementation deps['org.apache.sshd:sshd-sftp']
testImplementation deps['org.apache.tomcat:tomcat-annotations-api']
implementation deps['org.bouncycastle:bcpg-jdk18on']
implementation deps['org.bouncycastle:bcpkix-jdk18on']
implementation deps['org.bouncycastle:bcprov-jdk18on']
implementation deps['org.bouncycastle:bcpg-jdk15on']
implementation deps['org.bouncycastle:bcpkix-jdk15on']
implementation deps['org.bouncycastle:bcprov-jdk15on']
testImplementation deps['com.fasterxml.jackson.core:jackson-databind']
runtime deps['org.glassfish.jaxb:jaxb-runtime']
implementation deps['org.hibernate:hibernate-core']
implementation deps['org.hibernate:hibernate-hikaricp']
implementation deps['org.joda:joda-money']
@@ -247,7 +273,7 @@ dependencies {
implementation deps['us.fatehi:schemacrawler-diagram']
implementation deps['us.fatehi:schemacrawler-tools']
implementation deps['xerces:xmlParserAPIs']
implementation deps['org.ogce:xpp3']
implementation deps['xpp3:xpp3']
// This dependency must come after javax.mail:mail as it would otherwise
// shadow classes in package javax.mail with its own implementation.
implementation deps['com.google.appengine:appengine-api-1.0-sdk']
@@ -274,6 +300,7 @@ dependencies {
testImplementation deps['com.google.monitoring-client:contrib']
testImplementation deps['com.google.protobuf:protobuf-java-util']
testImplementation deps['com.google.truth:truth']
testImplementation deps['com.google.truth.extensions:truth-java8-extension']
testImplementation deps['org.checkerframework:checker-qual']
testImplementation deps['org.hamcrest:hamcrest']
testImplementation deps['org.hamcrest:hamcrest-core']
@@ -288,6 +315,7 @@ dependencies {
testImplementation deps['org.junit.platform:junit-platform-suite-api']
testImplementation deps['org.mockito:mockito-core']
testImplementation deps['org.mockito:mockito-junit-jupiter']
runtime deps['org.postgresql:postgresql']
// Indirect dependency found by undeclared-dependency check. Such
// dependencies should go after all other implementation and testImplementation
@@ -748,7 +776,7 @@ if (environment == 'alpha') {
gs://${gcpProject}-deploy/live/beam/${metaDataBaseName} \
--image-gcr-path ${imageName}:live \
--sdk-language JAVA \
--flex-template-base-image gcr.io/dataflow-templates-base/java21-template-launcher-base:latest \
--flex-template-base-image JAVA11 \
--metadata-file ${projectDir}/src/main/resources/${metaData} \
--jar ${uberJarName} \
--env FLEX_TEMPLATE_JAVA_MAIN_CLASS=${mainClass} \
@@ -928,6 +956,16 @@ task fragileTest(type: FilteringTest) {
}
}
task outcastTest(type: FilteringTest) {
tests = outcastTestPatterns
// Sets the maximum number of test executors that may exist at the same time.
// Note that this number appears to contribute to NoClassDefFoundError
// exceptions on certain machines and distros. The root cause is unclear.
// Try reducing this number if you experience similar problems.
maxParallelForks 3
}
// Dedicated test suite for schema-dependent tests.
task sqlIntegrationTest(type: FilteringTest) {
// TestSuite still requires a JUnit 4 runner, which knows how to handle JUnit 5 tests.
@@ -951,6 +989,7 @@ task registryToolIntegrationTest(dependsOn: nomulus, type: FilteringTest) {
task standardTest(type: FilteringTest) {
includeAllTests()
exclude fragileTestPatterns
exclude outcastTestPatterns
// See SqlIntegrationTestSuite.java
exclude '**/*BeforeSuiteTest.*', '**/*AfterSuiteTest.*'
@@ -967,7 +1006,7 @@ task standardTest(type: FilteringTest) {
// Also, Gradle executes tests in 1 thread and some of our test infrastructures
// depend on that, e.g. DualDatabaseTestInvocationContextProvider injects
// different implementation of TransactionManager into TransactionManagerFactory.
maxParallelForks 64
maxParallelForks 5
systemProperty 'test.projectRoot', rootProject.projectRootDir
systemProperty 'test.resourcesDir', resourcesDir
@@ -978,11 +1017,11 @@ test {
// FilteringTest tasks.
exclude "**"
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
// When we override tests, we also break the cleanTest command.
cleanTest.dependsOn(cleanFragileTest, cleanStandardTest,
cleanTest.dependsOn(cleanFragileTest, cleanOutcastTest, cleanStandardTest,
cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest)
project.build.dependsOn devtool

View File

@@ -2,185 +2,180 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
antlr:antlr:2.7.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
aopalliance:aopalliance:1.0=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.0.23=soy
aopalliance:aopalliance:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.0.23=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.0.26=css
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
cglib:cglib-nodep:2.2=css
com.101tec:zkclient:0.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.beust:jcommander:1.60=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-core:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-databind:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.15.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml:classmate:1.5.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-api:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport-zerodep:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport:3.3.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jffi:1.3.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:2.9.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-api:3.3.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport-zerodep:3.3.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport:3.3.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jffi:1.3.11=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-a64asm:1.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-constants:0.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-enxio:0.32.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-ffi:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-posix:3.1.19=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-unixsocket:0.38.22=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-enxio:0.32.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-ffi:2.2.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-posix:3.1.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-unixsocket:0.38.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-appengine:2.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-appengine:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-java6:2.1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-servlet:2.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-java6:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-servlet:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api-client:google-api-client:1.35.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.108.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.30.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.172.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.109.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.22.6-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:2.41.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.165.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.165.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.26.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.106.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.23.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:2.41.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.165.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.165.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.26.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.26.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.107.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:1.64.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.34.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.108.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.12.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.35.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.127.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.127.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.36.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20240304-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-appengine:v1-rev20240226-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20230812-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20230806-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20240113-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.24.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.106.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.12.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.23.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.113.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.32.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.32.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-appengine:v1-rev20230831-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20230520-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20230129-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20220920-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20231218-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20240110-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20230510-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-monitoring:v3-rev20240303-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-monitoring:v3-rev20230806-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sheets:v4-rev20230815-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20240304-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20240209-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-api-1.0-sdk:2.0.25=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-api-stubs:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-remote-api:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-testing:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-tools-sdk:2.0.25=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.apis:google-api-services-sqladmin:v1beta4-rev20230831-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20230617-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-api-1.0-sdk:1.9.86=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.appengine:appengine-api-1.0-sdk:2.0.19=testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-api-stubs:2.0.19=testCompileClasspath,testRuntimeClasspath
com.google.appengine:appengine-testing:1.9.86=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor
com.google.auto.value:auto-value-annotations:1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value:1.10.4=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value:1.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value:1.10.4=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:0.10=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor
com.google.closure-stylesheets:closure-stylesheets:1.5.0=css
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.17.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.17.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.17.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable-stats:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.16.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.14.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:2.41.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable-stats:2.26.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.26.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.22.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.22.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:1.82.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-monitoring:3.34.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.127.14=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.126.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsublite:1.12.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.56.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:grpc-gcp:1.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.16.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.24.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.126.19=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.124.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsublite:1.12.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.45.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.22.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:grpc-gcp:1.4.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.1=css
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.7=css,soy
com.google.common.html.types:types:1.0.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.dagger:dagger-compiler:2.51=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-spi:2.51=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger:2.51=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.26.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.dagger:dagger-compiler:2.48=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-producers:2.48=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-spi:2.48=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger:2.48=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.devtools.ksp:symbol-processing-api:1.9.0-1.0.12=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.18.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.21.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.3.4=errorprone,nonprodAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle,soy
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_check_api:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.3.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:javac-shaded:9-dev-r4023-3=annotationProcessor,testAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.escapevelocity:escapevelocity:0.9.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flatbuffers:flatbuffers-java:1.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.googlejavaformat:google-java-format:1.5=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=checkstyle,errorprone,nonprodAnnotationProcessor,soy
com.google.guava:failureaccess:1.0.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor
com.google.guava:guava-testlib:33.1.0-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.2-jre=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-testlib:32.1.2-jre=testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:20.0=css
com.google.guava:guava:27.0.1-jre=errorprone,nonprodAnnotationProcessor
com.google.guava:guava:31.0.1-jre=checkstyle,soy
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.1.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:32.1.2-jre=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-gson:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-gson:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-protobuf:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:1.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:1.43.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject.extensions:guice-multibindings:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:4.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.inject:guice:7.0.0=soy
com.google.j2objc:j2objc-annotations:1.1=errorprone,nonprodAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.3=checkstyle,soy
com.google.j2objc:j2objc-annotations:2.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.javascript:closure-compiler-externs:v20160713=css
com.google.javascript:closure-compiler-unshaded:v20160713=css
com.google.javascript:closure-compiler:v20210505=closureCompiler
@@ -189,110 +184,90 @@ com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,deploy_jar,non
com.google.monitoring-client:contrib:1.0.7=testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:metrics:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:stackdriver:1.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-appengine:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-java6:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-jetty:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-servlet:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client:1.35.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:3.25.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-appengine:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-java6:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-jetty:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client-servlet:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.oauth-client:google-oauth-client:1.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:3.23.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:2.5.0=css
com.google.protobuf:protobuf-java:3.13.0=soy
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:3.25.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.23.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.0.0-rc-2=soy
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2021-02-01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.4.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.truth.extensions:truth-java8-extension:1.1.5=testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.1.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:57.1=soy
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.ibm.icu:icu4j:57.1=compileClasspath,nonprodCompileClasspath,soy,testCompileClasspath
com.ibm.icu:icu4j:73.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.jcraft:jsch:0.1.55=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.lmax:disruptor:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.puppycrawl.tools:checkstyle:9.3=checkstyle
com.squareup.okhttp3:okhttp:4.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-bom:3.0.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.okio:okio-fakefilesystem-jvm:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-fakefilesystem:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-jvm:3.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio:3.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-compiler:4.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-grpc-server-generator:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.wire:wire-grpc-server:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.wire:wire-java-generator:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.wire:wire-kotlin-generator:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.wire:wire-runtime-jvm:4.9.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-runtime:4.9.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-schema-jvm:4.9.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-schema:4.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.wire:wire-swift-generator:4.5.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup:javapoet:1.13.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.squareup:kotlinpoet-jvm:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okhttp3:okhttp:3.11.0=testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio:1.14.0=testCompileClasspath,testRuntimeClasspath
com.squareup:javapoet:1.13.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.11.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.activation:jakarta.activation:1.2.2=jaxb
com.sun.activation:javax.activation:1.2.0=jaxb
com.sun.istack:istack-commons-runtime:3.0.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.xml.bind:jaxb-impl:2.3.9=jaxb
com.sun.xml.bind:jaxb-osgi:4.0.5=jaxb
com.sun.xml.bind:jaxb-xjc:2.3.9=jaxb
com.sun.istack:istack-commons-runtime:4.1.2=nonprodRuntime,runtime
com.sun.xml.bind:jaxb-impl:2.3.3=jaxb
com.sun.xml.bind:jaxb-osgi:4.0.3=jaxb
com.sun.xml.bind:jaxb-xjc:2.3.3=jaxb
com.sun.xml.fastinfoset:FastInfoset:1.2.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.thoughtworks.paranamer:paranamer:2.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.zaxxer:HikariCP:5.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.thoughtworks.qdox:qdox:1.12.1=testCompileClasspath,testRuntimeClasspath
com.zaxxer:HikariCP:3.4.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-beanutils:commons-beanutils:1.9.4=checkstyle
commons-codec:commons-codec:1.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-codec:commons-codec:1.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-collections:commons-collections:3.2.2=checkstyle
commons-logging:commons-logging:1.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
dnsjava:dnsjava:3.5.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0=testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.kitfox:svgSalamander:1.1.3=testRuntimeClasspath
guru.nidi:graphviz-java-all-j2v8:0.18.1=testRuntimeClasspath
guru.nidi:graphviz-java:0.18.1=testRuntimeClasspath
dnsjava:dnsjava:3.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_linux_x86_64:4.6.0=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86:4.6.0=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi.com.kitfox:svgSalamander:1.1.3=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi:graphviz-java-all-j2v8:0.18.1=nonprodRuntime,runtime,testRuntimeClasspath
guru.nidi:graphviz-java:0.18.1=nonprodRuntime,runtime,testRuntimeClasspath
info.picocli:picocli:4.6.2=checkstyle
io.apicurio:apicurio-registry-protobuf-schema-utilities:3.0.0.M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.confluent:common-config:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.confluent:common-utils:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.confluent:kafka-avro-serializer:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.confluent:kafka-schema-registry-client:5.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.61.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.60.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-protobuf-lite:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-services:1.61.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-services:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.62.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.61.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-util:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-xds:1.61.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-xds:1.62.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-buffer:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-socks:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-handler-proxy:4.1.100.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-handler:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-resolver:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.classgraph:classgraph:4.8.104=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.java-diff-utils:java-diff-utils:4.12=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.56.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.56.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-services:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-xds:1.56.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-buffer:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-socks:4.1.87.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-common:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-handler-proxy:4.1.87.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-handler:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-resolver:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-tcnative-classes:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport-native-unix-common:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport:4.1.100.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport-native-unix-common:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport:4.1.87.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-api:0.31.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-contrib-grpc-metrics:0.31.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
@@ -305,19 +280,17 @@ io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=compileClasspath,depl
io.opencensus:opencensus-impl-core:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-impl:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-proto:0.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.1.3=jaxb
jakarta.inject:jakarta.inject-api:1.0.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.26.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.1.0=jaxb
jakarta.activation:jakarta.activation-api:2.1.2=nonprodRuntime,runtime
jakarta.inject:jakarta.inject-api:2.0.1=soy
jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=jaxb
jakarta.xml.bind:jakarta.xml.bind-api:4.0.0=jaxb,nonprodRuntime,runtime
javacc:javacc:4.1=css
javax.activation:activation:1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.activation:javax.activation-api:1.2.0=compileClasspath,deploy_jar,jaxb,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.mail:mail:1.5.0-b01=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.persistence:javax.persistence-api:2.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
@@ -328,12 +301,12 @@ javax.xml.bind:jaxb-api:2.4.0-b180830.0359=jaxb
jline:jline:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
joda-time:joda-time:2.10.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.14.12=testCompileClasspath,testRuntimeClasspath
net.arnx:nashorn-promise:0.1.1=nonprodRuntime,runtime,testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.14.6=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.12.18=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
net.bytebuddy:byte-buddy:1.14.12=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.6=testCompileClasspath,testRuntimeClasspath
net.java.dev.javacc:javacc:4.1=css
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.java.dev.jna:jna:5.12.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
@@ -341,60 +314,61 @@ org.apache.arrow:arrow-format:5.0.0=compileClasspath,deploy_jar,nonprodCompileCl
org.apache.arrow:arrow-memory-core:5.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-vector:5.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.8.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-construction-java:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.54.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-fn-execution:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-kafka:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-transform-service-launcher:2.54.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_60_1:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-construction-java:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.50.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-fn-execution:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-kafka:2.50.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_54_0:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-compress:1.24.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-compress:1.23.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-csv:1.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-exec:1.3=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.13.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.apache.commons:commons-text:1.11.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-exec:1.3=nonprodRuntime,runtime,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.12.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.apache.commons:commons-text:1.10.0=testCompileClasspath,testRuntimeClasspath
org.apache.ftpserver:ftplet-api:1.2.0=testCompileClasspath,testRuntimeClasspath
org.apache.ftpserver:ftpserver-core:1.2.0=testCompileClasspath,testRuntimeClasspath
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.mina:mina-core:2.1.6=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:2.12.1=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:2.12.1=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:2.12.1=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:2.12.1=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.0-M18=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:2.0.0=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:2.0.0=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:2.0.0=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.0-M11=testCompileClasspath,testRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcpkix-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcprov-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcutil-jdk18on:1.77=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,testAnnotationProcessor
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.bouncycastle:bcpg-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcpkix-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcprov-jdk15on:1.67=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,nonprodCompileClasspath,nonprodRuntime,runtime,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.5=annotationProcessor,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testRuntimeClasspath
org.checkerframework:checker-qual:3.0.0=errorprone,nonprodAnnotationProcessor
org.checkerframework:checker-qual:3.12.0=checkstyle,soy
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor
org.checkerframework:checker-qual:3.41.0=annotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.42.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.31.0=nonprodRuntime,runtime
org.checkerframework:checker-qual:3.33.0=annotationProcessor,compileClasspath,nonprodCompileClasspath,testAnnotationProcessor
org.checkerframework:checker-qual:3.35.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:dataflow:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.checkerframework:javacutil:3.0.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.codehaus.jackson:jackson-core-asl:1.9.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.codehaus.jackson:jackson-mapper-asl:1.9.13=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.17=errorprone,nonprodAnnotationProcessor
org.codehaus.mojo:animal-sniffer-annotations:1.23=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.easymock:easymock:3.0=css
org.eclipse.angus:angus-activation:2.0.1=nonprodRuntime,runtime
org.eclipse.jetty:jetty-http:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -402,10 +376,12 @@ org.eclipse.jetty:jetty-server:9.4.49.v20220914=compileClasspath,deploy_jar,nonp
org.eclipse.jetty:jetty-servlet:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util-ajax:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:9.4.49.v20220914=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:10.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:10.10.0=testRuntimeClasspath
org.flywaydb:flyway-core:9.22.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.3=nonprodRuntime,runtime
org.glassfish.jaxb:jaxb-runtime:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-runtime:4.0.3=nonprodRuntime,runtime
org.glassfish.jaxb:txw2:2.3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.3=nonprodRuntime,runtime
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-core:1.1=css
org.hamcrest:hamcrest-core:1.3=nonprodCompileClasspath,nonprodRuntimeClasspath
@@ -416,71 +392,62 @@ org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
org.hibernate.common:hibernate-commons-annotations:5.1.2.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate:hibernate-core:5.6.15.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate:hibernate-hikaricp:5.6.15.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
org.jacoco:org.jacoco.agent:0.8.9=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.9=jacocoAnt
org.jacoco:org.jacoco.core:0.8.9=jacocoAnt
org.jacoco:org.jacoco.report:0.8.9=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jboss.logging:jboss-logging:3.4.3.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jboss:jandex:2.4.2.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-bom:1.4.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-reflect:1.6.10=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-reflect:1.9.20=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib:1.9.20=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-datetime:0.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10=annotationProcessor,testAnnotationProcessor
org.jetbrains.kotlin:kotlin-stdlib:1.9.0=annotationProcessor,testAnnotationProcessor
org.jetbrains:annotations:13.0=annotationProcessor,testAnnotationProcessor
org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:1.0.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:1.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.json:json:20160212=soy
org.json:json:20231013=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.17.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.2.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.10.2=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.10.2=testRuntimeClasspath
org.junit:junit-bom:5.10.2=testCompileClasspath,testRuntimeClasspath
org.json:json:20230618=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.16.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.1.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-migrationsupport:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.10.0=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.10.0=testRuntimeClasspath
org.junit:junit-bom:5.10.0=testCompileClasspath,testRuntimeClasspath
org.jvnet.staxex:stax-ex:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:1.10.19=css
org.mockito:mockito-core:5.11.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.11.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:5.5.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.5.0=testCompileClasspath,testRuntimeClasspath
org.mortbay.jetty:jetty-util:6.1.26=testCompileClasspath,testRuntimeClasspath
org.mortbay.jetty:jetty:6.1.26=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:2.1=css
org.objenesis:objenesis:3.3=testRuntimeClasspath
org.ogce:xpp3:1.1.6=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:7.0=soy
org.ow2.asm:asm-analysis:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-analysis:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:7.0=soy
org.ow2.asm:asm-commons:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.6=jacocoAnt
org.ow2.asm:asm-commons:9.5=jacocoAnt
org.ow2.asm:asm-tree:7.0=soy
org.ow2.asm:asm-tree:9.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.6=jacocoAnt
org.ow2.asm:asm-util:7.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.5=compileClasspath,deploy_jar,jacocoAnt,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-util:7.0=soy
org.ow2.asm:asm-util:9.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:7.0=soy
org.ow2.asm:asm:9.2=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm:9.6=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.7.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.5=compileClasspath,deploy_jar,jacocoAnt,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.pcollections:pcollections:2.1.2=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.plumelib:plume-util:1.0.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.plumelib:reflection-util:0.0.2=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.plumelib:require-javadoc:0.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.6.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntime,nonprodRuntimeClasspath,runtime,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:3.141.59=testCompileClasspath,testRuntimeClasspath
@@ -493,31 +460,32 @@ org.seleniumhq.selenium:selenium-opera-driver:3.141.59=testCompileClasspath,test
org.seleniumhq.selenium:selenium-remote-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:3.141.59=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:3.141.59=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
org.slf4j:slf4j-api:2.0.12=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath
org.slf4j:slf4j-api:2.1.0-alpha1=deploy_jar,runtimeClasspath,testRuntimeClasspath
org.slf4j:slf4j-jdk14:2.1.0-alpha1=deploy_jar,runtimeClasspath,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.30=nonprodRuntime,runtime,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=nonprodRuntime,runtime,testRuntimeClasspath
org.slf4j:slf4j-api:1.7.30=nonprodRuntime,runtime
org.slf4j:slf4j-api:1.7.36=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath
org.slf4j:slf4j-api:2.0.9=deploy_jar,runtimeClasspath,testRuntimeClasspath
org.slf4j:slf4j-jdk14:2.0.9=deploy_jar,runtimeClasspath,testRuntimeClasspath
org.springframework:spring-core:5.3.27=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.springframework:spring-expression:5.3.27=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.springframework:spring-jcl:5.3.27=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:database-commons:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:jdbc:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:junit-jupiter:1.19.7=testCompileClasspath,testRuntimeClasspath
org.testcontainers:postgresql:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:selenium:1.19.7=testCompileClasspath,testRuntimeClasspath
org.testcontainers:testcontainers:1.19.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:database-commons:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:jdbc:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:junit-jupiter:1.19.0=testCompileClasspath,testRuntimeClasspath
org.testcontainers:postgresql:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.testcontainers:selenium:1.19.0=testCompileClasspath,testRuntimeClasspath
org.testcontainers:testcontainers:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.threeten:threetenbp:1.6.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.tukaani:xz:1.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.yaml:snakeyaml:2.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.webjars.npm:viz.js-graphviz-java:2.1.3=nonprodRuntime,runtime,testRuntimeClasspath
org.xerial.snappy:snappy-java:1.1.10.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.yaml:snakeyaml:2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-api:16.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:16.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-tools:16.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-utility:16.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:16.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool,nomulus_test
xpp3:xpp3:1.1.4c=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool,errorproneJavac,nomulus_test

View File

@@ -40,6 +40,7 @@ import org.joda.time.DateTime;
@Module
public class BatchModule {
public static final String PARAM_DRY_RUN = "dryRun";
public static final String PARAM_FAST = "fast";
@Provides
@@ -137,4 +138,10 @@ public class BatchModule {
static boolean provideIsFast(HttpServletRequest req) {
return extractBooleanParameter(req, PARAM_FAST);
}
@Provides
@Parameter(PARAM_DRY_RUN)
static boolean provideIsDryRun(HttpServletRequest req) {
return extractBooleanParameter(req, PARAM_DRY_RUN);
}
}

View File

@@ -207,7 +207,7 @@ public class CloudTasksUtils implements Serializable {
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
if (jitterSeconds.isEmpty() || jitterSeconds.get() <= 0) {
if (!jitterSeconds.isPresent() || jitterSeconds.get() <= 0) {
return createTask(path, method, service, params);
}
return createTaskWithDelay(

View File

@@ -171,7 +171,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
tm().transact(
() -> {
Domain transDomain = tm().loadByKey(domain.createVKey());
if (domain.getAutorenewEndTime().isEmpty()
if (!domain.getAutorenewEndTime().isPresent()
|| domain.getAutorenewEndTime().get().isAfter(tm().getTransactionTime())) {
logger.atSevere().log(
"Failed to delete domain %s because of its autorenew end time: %s.",

View File

@@ -16,15 +16,16 @@ package google.registry.batch;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
import static google.registry.config.RegistryEnvironment.PRODUCTION;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.RegistryEnvironment.PRODUCTION;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryEnvironment;
import google.registry.flows.poll.PollFlowUtils;
import google.registry.model.EppResource;
import google.registry.model.EppResourceUtils;
@@ -39,7 +40,6 @@ import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import javax.inject.Inject;
/**

View File

@@ -17,14 +17,14 @@ package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
import static google.registry.config.RegistryEnvironment.PRODUCTION;
import static google.registry.dns.DnsUtils.requestDomainDnsRefresh;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
import static google.registry.model.tld.Tlds.getTldsOfType;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static google.registry.request.RequestParameters.PARAM_TLDS;
import static google.registry.util.RegistryEnvironment.PRODUCTION;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
@@ -32,6 +32,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.EppResourceUtils;
import google.registry.model.domain.Domain;
@@ -40,7 +41,6 @@ import google.registry.model.tld.Tld.TldType;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.RegistryEnvironment;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import org.hibernate.CacheMode;

View File

@@ -15,10 +15,10 @@
package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
import static google.registry.beam.BeamUtils.createJobName;
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_OK;
@@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import google.registry.beam.billing.ExpandBillingRecurrencesPipeline;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingRecurrence;
import google.registry.model.common.Cursor;
@@ -39,7 +40,6 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import java.io.IOException;
import java.util.Optional;
import javax.inject.Inject;

View File

@@ -82,6 +82,7 @@ public class RelockDomainAction implements Runnable {
private final long oldUnlockRevisionId;
private final int previousAttempts;
private final InternetAddress alertRecipientAddress;
private final InternetAddress gSuiteOutgoingEmailAddress;
private final String supportEmail;
private final GmailClient gmailClient;
private final DomainLockUtils domainLockUtils;
@@ -92,6 +93,7 @@ public class RelockDomainAction implements Runnable {
@Parameter(OLD_UNLOCK_REVISION_ID_PARAM) long oldUnlockRevisionId,
@Parameter(PREVIOUS_ATTEMPTS_PARAM) int previousAttempts,
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
@Config("supportEmail") String supportEmail,
GmailClient gmailClient,
DomainLockUtils domainLockUtils,
@@ -99,6 +101,7 @@ public class RelockDomainAction implements Runnable {
this.oldUnlockRevisionId = oldUnlockRevisionId;
this.previousAttempts = previousAttempts;
this.alertRecipientAddress = alertRecipientAddress;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
this.supportEmail = supportEmail;
this.gmailClient = gmailClient;
this.domainLockUtils = domainLockUtils;
@@ -214,6 +217,7 @@ public class RelockDomainAction implements Runnable {
supportEmail);
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
@@ -243,6 +247,7 @@ public class RelockDomainAction implements Runnable {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Successful re-lock of domain %s", oldLock.getDomainName()))
.setRecipients(getEmailRecipients(oldLock.getRegistrarId()))
@@ -261,6 +266,7 @@ public class RelockDomainAction implements Runnable {
.build();
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(body)
.setSubject(String.format("Error re-locking domain %s", oldLock.getDomainName()))
.setRecipients(allRecipients)
@@ -270,6 +276,7 @@ public class RelockDomainAction implements Runnable {
private void sendUnknownRevisionIdAlertEmail() {
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setBody(String.format(RELOCK_UNKNOWN_ID_FAILURE_EMAIL_TEMPLATE, oldUnlockRevisionId))
.setSubject("Error re-locking domain")
.setRecipients(ImmutableSet.of(alertRecipientAddress))

View File

@@ -27,12 +27,12 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import javax.inject.Inject;
/**

View File

@@ -21,6 +21,7 @@ import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_OK;
import static org.joda.time.DateTimeZone.UTC;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -38,6 +39,7 @@ import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.EmailMessage;
import java.util.Date;
import java.util.Optional;
import javax.inject.Inject;
import javax.mail.internet.AddressException;
@@ -72,18 +74,21 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
private final String expirationWarningEmailBodyText;
private final GmailClient gmailClient;
private final String expirationWarningEmailSubjectText;
private final InternetAddress gSuiteOutgoingEmailAddress;
private final Response response;
@Inject
public SendExpiringCertificateNotificationEmailAction(
@Config("expirationWarningEmailBodyText") String expirationWarningEmailBodyText,
@Config("expirationWarningEmailSubjectText") String expirationWarningEmailSubjectText,
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
GmailClient gmailClient,
CertificateChecker certificateChecker,
Response response) {
this.certificateChecker = certificateChecker;
this.expirationWarningEmailSubjectText = expirationWarningEmailSubjectText;
this.gmailClient = gmailClient;
this.gSuiteOutgoingEmailAddress = gSuiteOutgoingEmailAddress;
this.expirationWarningEmailBodyText = expirationWarningEmailBodyText;
this.response = response;
}
@@ -121,7 +126,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
return Streams.stream(Registrar.loadAllCached())
.map(
registrar ->
new RegistrarInfo(
RegistrarInfo.create(
registrar,
registrar.getClientCertificate().isPresent()
&& certificateChecker.shouldReceiveExpiringNotification(
@@ -147,7 +152,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
DateTime lastExpiringCertNotificationSentDate,
CertificateType certificateType,
Optional<String> certificate) {
if (certificate.isEmpty()
if (!certificate.isPresent()
|| !certificateChecker.shouldReceiveExpiringNotification(
lastExpiringCertNotificationSentDate, certificate.get())) {
return false;
@@ -155,11 +160,12 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
try {
ImmutableSet<InternetAddress> recipients = getEmailAddresses(registrar, Type.TECH);
ImmutableSet<InternetAddress> ccs = getEmailAddresses(registrar, Type.ADMIN);
DateTime expirationDate =
new DateTime(certificateChecker.getCertificate(certificate.get()).getNotAfter());
Date expirationDate = certificateChecker.getCertificate(certificate.get()).getNotAfter();
logger.atInfo().log(
" %s SSL certificate of registrar '%s' will expire on %s.",
certificateType.getDisplayName(), registrar.getRegistrarName(), expirationDate);
certificateType.getDisplayName(),
registrar.getRegistrarName(),
expirationDate.toString());
if (recipients.isEmpty() && ccs.isEmpty()) {
logger.atWarning().log(
"Registrar %s contains no TECH nor ADMIN email addresses to receive notification"
@@ -169,6 +175,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
}
gmailClient.sendEmail(
EmailMessage.newBuilder()
.setFrom(gSuiteOutgoingEmailAddress)
.setSubject(expirationWarningEmailSubjectText)
.setBody(
getEmailBody(
@@ -295,7 +302,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@VisibleForTesting
@SuppressWarnings("lgtm[java/dereferenced-value-may-be-null]")
String getEmailBody(
String registrarName, CertificateType type, DateTime expirationDate, String registrarId) {
String registrarName, CertificateType type, Date expirationDate, String registrarId) {
checkArgumentNotNull(expirationDate, "Expiration date cannot be null");
checkArgumentNotNull(type, "Certificate type cannot be null");
checkArgumentNotNull(registrarId, "Registrar Id cannot be null");
@@ -303,7 +310,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
expirationWarningEmailBodyText,
registrarName,
type.getDisplayName(),
DATE_FORMATTER.print(expirationDate),
DATE_FORMATTER.print(new DateTime(expirationDate)),
registrarId);
}
@@ -328,6 +335,19 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
}
}
record RegistrarInfo(
Registrar registrar, boolean isCertExpiring, boolean isFailOverCertExpiring) {}
@AutoValue
public abstract static class RegistrarInfo {
static RegistrarInfo create(
Registrar registrar, boolean isCertExpiring, boolean isFailOverCertExpiring) {
return new AutoValue_SendExpiringCertificateNotificationEmailAction_RegistrarInfo(
registrar, isCertExpiring, isFailOverCertExpiring);
}
public abstract Registrar registrar();
public abstract boolean isCertExpiring();
public abstract boolean isFailOverCertExpiring();
}
}

View File

@@ -14,8 +14,8 @@
package google.registry.batch;
import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
import static google.registry.beam.BeamUtils.createJobName;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_OK;
@@ -28,6 +28,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.beam.wipeout.WipeOutContactHistoryPiiPipeline;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.model.contact.ContactHistory;
import google.registry.request.Action;
import google.registry.request.Action.Service;
@@ -35,7 +36,6 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import java.io.IOException;
import java.util.Optional;
import javax.inject.Inject;

View File

@@ -21,21 +21,26 @@ import google.registry.reporting.billing.BillingModule;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.regex.Pattern;
import org.apache.beam.sdk.coders.AtomicCoder;
import org.apache.beam.sdk.coders.Coder;
import org.apache.beam.sdk.coders.DoubleCoder;
import org.apache.beam.sdk.coders.NullableCoder;
import org.apache.beam.sdk.coders.StringUtf8Coder;
import org.apache.beam.sdk.coders.VarIntCoder;
import org.apache.beam.sdk.coders.VarLongCoder;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/** A POJO representing a single billable event, parsed from a {@code SchemaAndRecord}. */
/**
* A POJO representing a single billable event, parsed from a {@code SchemaAndRecord}.
*
* <p>This is a trivially serializable class that allows Beam to transform the results of a Cloud
* SQL query into a standard Java representation, giving us the type guarantees and ease of
* manipulation Cloud SQL lacks.
*/
@AutoValue
public abstract class BillingEvent {
public abstract class BillingEvent implements Serializable {
private static final long serialVersionUID = -3593088371541450077L;
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss zzz");
@@ -80,7 +85,7 @@ public abstract class BillingEvent {
/** Returns the tld this event was generated for. */
abstract String tld();
/** Returns the billable action this event was generated for (i.e., RENEW, CREATE, TRANSFER...) */
/** Returns the billable action this event was generated for (i.e. RENEW, CREATE, TRANSFER...) */
abstract String action();
/** Returns the fully qualified domain name this event was generated for. */
@@ -92,7 +97,7 @@ public abstract class BillingEvent {
/** Returns the number of years this billing event is made out for. */
abstract int years();
/** Returns the 3-letter currency code for the billing event (i.e., USD or JPY.) */
/** Returns the 3-letter currency code for the billing event (i.e. USD or JPY.) */
abstract String currency();
/** Returns the cost associated with this billing event. */
@@ -198,7 +203,9 @@ public abstract class BillingEvent {
/** Key for each {@code BillingEvent}, when aggregating for the overall invoice. */
@AutoValue
abstract static class InvoiceGroupingKey {
abstract static class InvoiceGroupingKey implements Serializable {
private static final long serialVersionUID = -151561764235256205L;
private static final ImmutableList<String> INVOICE_HEADERS =
ImmutableList.of(
@@ -270,14 +277,8 @@ public abstract class BillingEvent {
/** Coder that provides deterministic (de)serialization for {@code InvoiceGroupingKey}. */
static class InvoiceGroupingKeyCoder extends AtomicCoder<InvoiceGroupingKey> {
private static final Coder<String> stringCoder = StringUtf8Coder.of();
private static final InvoiceGroupingKeyCoder INSTANCE = new InvoiceGroupingKeyCoder();
public static InvoiceGroupingKeyCoder of() {
return INSTANCE;
}
private InvoiceGroupingKeyCoder() {}
private static final long serialVersionUID = 6680701524304107547L;
@Override
public void encode(InvoiceGroupingKey value, OutputStream outStream) throws IOException {
@@ -294,6 +295,7 @@ public abstract class BillingEvent {
@Override
public InvoiceGroupingKey decode(InputStream inStream) throws IOException {
Coder<String> stringCoder = StringUtf8Coder.of();
return new AutoValue_BillingEvent_InvoiceGroupingKey(
stringCoder.decode(inStream),
stringCoder.decode(inStream),
@@ -306,55 +308,4 @@ public abstract class BillingEvent {
}
}
}
static class BillingEventCoder extends AtomicCoder<BillingEvent> {
private static final Coder<String> stringCoder = StringUtf8Coder.of();
private static final Coder<Integer> integerCoder = VarIntCoder.of();
private static final Coder<Long> longCoder = VarLongCoder.of();
private static final Coder<Double> doubleCoder = DoubleCoder.of();
private static final BillingEventCoder INSTANCE = new BillingEventCoder();
static NullableCoder<BillingEvent> ofNullable() {
return NullableCoder.of(INSTANCE);
}
private BillingEventCoder() {}
@Override
public void encode(BillingEvent value, OutputStream outStream) throws IOException {
longCoder.encode(value.id(), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.print(value.billingTime()), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.print(value.eventTime()), outStream);
stringCoder.encode(value.registrarId(), outStream);
stringCoder.encode(value.billingId(), outStream);
stringCoder.encode(value.poNumber(), outStream);
stringCoder.encode(value.tld(), outStream);
stringCoder.encode(value.action(), outStream);
stringCoder.encode(value.domain(), outStream);
stringCoder.encode(value.repositoryId(), outStream);
integerCoder.encode(value.years(), outStream);
stringCoder.encode(value.currency(), outStream);
doubleCoder.encode(value.amount(), outStream);
stringCoder.encode(value.flags(), outStream);
}
@Override
public BillingEvent decode(InputStream inStream) throws IOException {
return new AutoValue_BillingEvent(
longCoder.decode(inStream),
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
integerCoder.decode(inStream),
stringCoder.decode(inStream),
doubleCoder.decode(inStream),
stringCoder.decode(inStream));
}
}
}

View File

@@ -18,7 +18,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static org.apache.beam.sdk.values.TypeDescriptors.strings;
import com.google.common.flogger.FluentLogger;
import google.registry.beam.billing.BillingEvent.BillingEventCoder;
import google.registry.beam.billing.BillingEvent.InvoiceGroupingKey;
import google.registry.beam.billing.BillingEvent.InvoiceGroupingKey.InvoiceGroupingKeyCoder;
import google.registry.beam.common.RegistryJpaIO;
@@ -31,7 +30,6 @@ import google.registry.reporting.billing.BillingModule;
import google.registry.util.DomainNameUtils;
import google.registry.util.ResourceUtils;
import google.registry.util.SqlTemplate;
import java.io.Serial;
import java.io.Serializable;
import java.time.YearMonth;
import java.util.Objects;
@@ -39,13 +37,13 @@ import java.util.Optional;
import java.util.regex.Pattern;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.coders.SerializableCoder;
import org.apache.beam.sdk.coders.StringUtf8Coder;
import org.apache.beam.sdk.io.FileIO;
import org.apache.beam.sdk.io.TextIO;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.Contextful;
import org.apache.beam.sdk.transforms.Count;
import org.apache.beam.sdk.transforms.Distinct;
import org.apache.beam.sdk.transforms.Filter;
import org.apache.beam.sdk.transforms.MapElements;
import org.apache.beam.sdk.transforms.PTransform;
@@ -67,7 +65,7 @@ import org.joda.money.CurrencyUnit;
*/
public class InvoicingPipeline implements Serializable {
@Serial private static final long serialVersionUID = 5386330443625580081L;
private static final long serialVersionUID = 5386330443625580081L;
private static final Pattern SQL_COMMENT_REGEX =
Pattern.compile("^\\s*--.*\\n", Pattern.MULTILINE);
@@ -99,11 +97,13 @@ public class InvoicingPipeline implements Serializable {
Read<Object[], google.registry.beam.billing.BillingEvent> read =
RegistryJpaIO.<Object[], google.registry.beam.billing.BillingEvent>read(
makeCloudSqlQuery(options.getYearMonth()), false, row -> parseRow(row).orElse(null))
.withCoder(BillingEventCoder.ofNullable());
return pipeline
.apply("Read BillingEvents from Cloud SQL", read)
.apply("Remove null elements", Filter.by(Objects::nonNull))
.apply("Remove duplicates", Distinct.create());
.withCoder(SerializableCoder.of(google.registry.beam.billing.BillingEvent.class));
PCollection<google.registry.beam.billing.BillingEvent> billingEventsWithNulls =
pipeline.apply("Read BillingEvents from Cloud SQL", read);
// Remove null billing events
return billingEventsWithNulls.apply(Filter.by(Objects::nonNull));
}
private static Optional<google.registry.beam.billing.BillingEvent> parseRow(Object[] row) {
@@ -142,7 +142,7 @@ public class InvoicingPipeline implements Serializable {
extends PTransform<
PCollection<google.registry.beam.billing.BillingEvent>, PCollection<String>> {
@Serial private static final long serialVersionUID = -8090619008258393728L;
private static final long serialVersionUID = -8090619008258393728L;
@Override
public PCollection<String> expand(
@@ -152,9 +152,9 @@ public class InvoicingPipeline implements Serializable {
"Map to invoicing key",
MapElements.into(TypeDescriptor.of(InvoiceGroupingKey.class))
.via(google.registry.beam.billing.BillingEvent::getInvoiceGroupingKey))
.setCoder(InvoiceGroupingKeyCoder.of())
.apply(
"Filter out free events", Filter.by((InvoiceGroupingKey key) -> key.unitPrice() != 0))
.setCoder(new InvoiceGroupingKeyCoder())
.apply("Count occurrences", Count.perElement())
.apply(
"Format as CSVs",
@@ -163,12 +163,7 @@ public class InvoicingPipeline implements Serializable {
}
}
/**
* Saves the billing events to a single overall invoice CSV file. TextIO always produces the file
* of type text/plain, which we then update to desired text/csv before sending an email to billing
* team {@link google.registry.reporting.billing.BillingEmailUtils#emailOverallInvoice()
* emailOverallInvoice}
*/
/** Saves the billing events to a single overall invoice CSV file. */
static void saveInvoiceCsv(
PCollection<google.registry.beam.billing.BillingEvent> billingEvents,
InvoicingPipelineOptions options) {

View File

@@ -209,16 +209,9 @@ public final class RegistryJpaIO {
@ProcessElement
public void processElement(OutputReceiver<T> outputReceiver) {
// Note the use of no-retry transaction here. The results from the query are streamed to the
// output receiver inside the transaction, which cannot be rolled back in case of a retry,
// which in turn results in duplicate elements. If we try to pass the results to the output
// receiver outside the transaction, they have to be materialized into a list containing all
// the elements (without resorting to manual pagination) and greatly decrease the
// parallelism of the pipeline.
tm().transactNoRetry(
tm().transact(
() -> {
query.stream().map(resultMapper::apply).forEach(outputReceiver::output);
return null;
});
}
}

View File

@@ -14,9 +14,9 @@
package google.registry.beam.common;
import google.registry.config.RegistryEnvironment;
import google.registry.persistence.PersistenceModule.JpaTransactionManagerType;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.util.RegistryEnvironment;
import java.util.Objects;
import javax.annotation.Nullable;
import org.apache.beam.sdk.extensions.gcp.options.GcpOptions;
@@ -63,7 +63,7 @@ public interface RegistryPipelineOptions extends GcpOptions {
}
/**
* Validates the GCP project and Registry environment settings in {@code options}. If project is
* Validates the GCP project and Registry environment settings in {@code option}. If project is
* undefined, it is set according to the Registry environment; if project is defined but
* inconsistent with the Registry environment, an {@link IllegalArgumentException} will be thrown.
*

View File

@@ -19,10 +19,10 @@ import static google.registry.beam.common.RegistryPipelineOptions.toRegistryPipe
import com.google.auto.service.AutoService;
import com.google.common.flogger.FluentLogger;
import dagger.Lazy;
import google.registry.config.RegistryEnvironment;
import google.registry.config.SystemPropertySetter;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.persistence.transaction.TransactionManagerFactory;
import google.registry.util.RegistryEnvironment;
import google.registry.util.SystemPropertySetter;
import org.apache.beam.sdk.harness.JvmInitializer;
import org.apache.beam.sdk.options.PipelineOptions;

View File

@@ -144,7 +144,6 @@ public class RdeIO {
this.marshaller = new RdeMarshaller(validationMode);
}
@SuppressWarnings("unused")
@Setup
public void setup() {
Security.addProvider(new BouncyCastleProvider());

View File

@@ -116,14 +116,14 @@ import org.joda.time.DateTime;
* <p>The pipeline is broadly divided into two parts -- creating the {@link DepositFragment}s, and
* processing them.
*
* <h2>Creating {@link DepositFragment}</h2>
* <h1>Creating {@link DepositFragment}</h1>
*
* <h3>{@link Registrar}</h3>
* <h2>{@link Registrar}</h2>
*
* Non-test registrar entities are loaded from Cloud SQL and marshalled into deposit fragments. They
* are <b>NOT</b> rewound to the watermark.
*
* <h3>{@link EppResource}</h3>
* <h2>{@link EppResource}</h2>
*
* All EPP resources are loaded from the corresponding {@link HistoryEntry}, which has the resource
* embedded. In general, we find most recent history entry before watermark and filter out the ones
@@ -158,7 +158,7 @@ import org.joda.time.DateTime;
* watermark to the domain at watermark. We then proceed to create the (pending deposit: deposit
* fragment) pair for subordinate hosts using the added domain information.
*
* <h2>Processing {@link DepositFragment}</h2>
* <h1>Processing {@link DepositFragment}</h1>
*
* The (pending deposit: deposit fragment) pairs from different resources are combined and grouped
* by pending deposit. For each pending deposit, all the relevant deposit fragments are written into

View File

@@ -225,7 +225,7 @@ public class SafeBrowsingTransforms {
new JSONObject(
CharStreams.toString(
new InputStreamReader(response.getEntity().getContent(), UTF_8)));
logger.atInfo().log("Got response: %s", responseBody);
logger.atInfo().log("Got response: %s", responseBody.toString());
if (responseBody.length() == 0) {
logger.atInfo().log("Response was empty, no threats detected.");
} else {

View File

@@ -17,6 +17,7 @@ package google.registry.beam.spec11;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import dagger.Component;
import dagger.Module;
@@ -198,7 +199,7 @@ public class Spec11Pipeline implements Serializable {
(KV<DomainNameInfo, ThreatMatch> kv) ->
KV.of(
kv.getKey().registrarId(),
new EmailAndThreatMatch(
EmailAndThreatMatch.create(
kv.getKey().registrarEmailAddress(), kv.getValue()))))
.apply("Group by registrar client ID", GroupByKey.create())
.apply(
@@ -280,5 +281,15 @@ public class Spec11Pipeline implements Serializable {
Spec11Pipeline spec11Pipeline();
}
record EmailAndThreatMatch(String email, ThreatMatch threatMatch) implements Serializable {}
@AutoValue
abstract static class EmailAndThreatMatch implements Serializable {
abstract String email();
abstract ThreatMatch threatMatch();
static EmailAndThreatMatch create(String email, ThreatMatch threatMatch) {
return new AutoValue_Spec11Pipeline_EmailAndThreatMatch(email, threatMatch);
}
}
}

View File

@@ -144,8 +144,7 @@ public class BigqueryConnection implements AutoCloseable {
public Builder setPollInterval(Duration pollInterval) {
checkArgument(
!pollInterval.isShorterThan(MIN_POLL_INTERVAL),
"poll interval must be at least %s ms",
MIN_POLL_INTERVAL.getMillis());
"poll interval must be at least %ldms", MIN_POLL_INTERVAL.getMillis());
instance.pollInterval = pollInterval;
return this;
}
@@ -217,7 +216,7 @@ public class BigqueryConnection implements AutoCloseable {
}
public Builder timeToLive(Duration duration) {
this.table.setExpirationTime(DateTime.now(UTC).plus(duration).getMillis());
this.table.setExpirationTime(new DateTime(UTC).plus(duration).getMillis());
return this;
}
@@ -557,6 +556,7 @@ public class BigqueryConnection implements AutoCloseable {
/**
* Launch a job, but do not wait for it to complete.
*
* @throws BigqueryJobFailureException
*/
private Job launchJob(Job job, @Nullable AbstractInputStreamContent data) {
verify(job.getStatus() == null);
@@ -572,6 +572,7 @@ public class BigqueryConnection implements AutoCloseable {
/**
* Synchronously waits for a job to complete that's already been launched.
*
* @throws BigqueryJobFailureException
*/
private Job waitForJob(Job job) {
verify(job.getStatus() != null);
@@ -590,6 +591,7 @@ public class BigqueryConnection implements AutoCloseable {
/**
* Checks completed job for errors.
*
* @throws BigqueryJobFailureException
*/
private static Job checkJob(Job job) {
verify(job.getStatus() != null);

View File

@@ -72,7 +72,7 @@ public final class BigqueryJobFailureException extends RuntimeException {
/**
* Returns a short error code describing why this job failed.
*
* <p>Sample Reasons:
* <h3>Sample Reasons</h3>
*
* <ul>
* <li>{@code "duplicate"}: The table you're trying to create already exists.
@@ -80,8 +80,8 @@ public final class BigqueryJobFailureException extends RuntimeException {
* <li>{@code "unknown"}: Non-Bigquery errors.
* </ul>
*
* @see <a href="https://cloud.google.com/bigquery/troubleshooting-errors">Troubleshooting
* Errors</a>
* @see <a href="https://cloud.google.com/bigquery/troubleshooting-errors">
* Troubleshooting Errors</a>
*/
public String getReason() {
if (jobStatus != null) {

View File

@@ -14,10 +14,8 @@
package google.registry.bsa;
/**
* The product types of the block lists, which determines the http endpoint that serves the data.
*/
public enum BlockListType {
/** Identifiers of the BSA lists with blocking labels. */
public enum BlockList {
BLOCK,
BLOCK_PLUS;
}

View File

@@ -1,164 +0,0 @@
// Copyright 2023 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.bsa;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpMethods;
import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.ByteStreams;
import google.registry.bsa.api.BsaCredential;
import google.registry.bsa.api.BsaException;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.UrlConnectionService;
import google.registry.util.Retrier;
import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.net.ssl.HttpsURLConnection;
/** Fetches data from the BSA API. */
public class BlockListFetcher {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final UrlConnectionService urlConnectionService;
private final BsaCredential credential;
private final ImmutableMap<String, String> blockListUrls;
private final Retrier retrier;
@Inject
BlockListFetcher(
UrlConnectionService urlConnectionService,
BsaCredential credential,
@Config("bsaDataUrls") ImmutableMap<String, String> blockListUrls,
Retrier retrier) {
this.urlConnectionService = urlConnectionService;
this.credential = credential;
this.blockListUrls = blockListUrls;
this.retrier = retrier;
}
LazyBlockList fetch(BlockListType blockListType) {
// TODO: use more informative exceptions to describe retriable errors
return retrier.callWithRetry(
() -> tryFetch(blockListType),
e -> e instanceof BsaException && ((BsaException) e).isRetriable());
}
LazyBlockList tryFetch(BlockListType blockListType) {
try {
URL dataUrl = new URL(blockListUrls.get(blockListType.name()));
logger.atInfo().log("Downloading from %s", dataUrl);
HttpsURLConnection connection =
(HttpsURLConnection) urlConnectionService.createConnection(dataUrl);
connection.setRequestMethod(HttpMethods.GET);
connection.setRequestProperty("Authorization", "Bearer " + credential.getAuthToken());
int code = connection.getResponseCode();
if (code != SC_OK) {
String errorDetails = "";
try (InputStream errorStream = connection.getErrorStream()) {
errorDetails = new String(ByteStreams.toByteArray(errorStream), UTF_8);
} catch (NullPointerException e) {
// No error message.
} catch (Exception e) {
errorDetails = "Failed to retrieve error message: " + e.getMessage();
}
throw new BsaException(
String.format(
"Status code: [%s], error: [%s], details: [%s]",
code, connection.getResponseMessage(), errorDetails),
/* retriable= */ true);
}
return new LazyBlockList(blockListType, connection);
} catch (IOException e) {
throw new BsaException(e, /* retriable= */ true);
} catch (GeneralSecurityException e) {
throw new BsaException(e, /* retriable= */ false);
}
}
static class LazyBlockList implements Closeable {
private final BlockListType blockListType;
private final HttpsURLConnection connection;
private final BufferedInputStream inputStream;
private final String checksum;
LazyBlockList(BlockListType blockListType, HttpsURLConnection connection) throws IOException {
this.blockListType = blockListType;
this.connection = connection;
this.inputStream = new BufferedInputStream(connection.getInputStream());
this.checksum = readChecksum();
}
/** Reads the BSA-generated checksum, which is the first line of the input. */
private String readChecksum() throws IOException {
StringBuilder checksum = new StringBuilder();
char ch;
while ((ch = peekInputStream()) != Character.MAX_VALUE && !Character.isWhitespace(ch)) {
checksum.append((char) inputStream.read());
}
while ((ch = peekInputStream()) != Character.MAX_VALUE && Character.isWhitespace(ch)) {
inputStream.read();
}
return checksum.toString();
}
char peekInputStream() throws IOException {
inputStream.mark(1);
int byteValue = inputStream.read();
inputStream.reset();
return (char) byteValue;
}
BlockListType getName() {
return blockListType;
}
String checksum() {
return checksum;
}
void consumeAll(BiConsumer<byte[], Integer> consumer) throws IOException {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
consumer.accept(buffer, bytesRead);
}
}
@Override
public void close() {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// Fall through to close the connection.
}
}
connection.disconnect();
}
}
}

View File

@@ -1,269 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Multimaps.newListMultimap;
import static com.google.common.collect.Multimaps.toMultimap;
import com.google.auto.value.AutoValue;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import google.registry.bsa.api.BlockLabel;
import google.registry.bsa.api.BlockLabel.LabelType;
import google.registry.bsa.api.BlockOrder;
import google.registry.bsa.api.BlockOrder.OrderType;
import google.registry.bsa.persistence.DownloadSchedule;
import google.registry.bsa.persistence.DownloadSchedule.CompletedJob;
import google.registry.tldconfig.idn.IdnTableEnum;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
/** Creates diffs between the most recent download and the previous one. */
class BsaDiffCreator {
private static final Splitter LINE_SPLITTER = Splitter.on(',').trimResults();
private static final Splitter ORDER_SPLITTER = Splitter.on(';').trimResults();
private static final String BSA_CSV_HEADER = "domainLabel,orderIDs";
/** An impossible value for order ID. See {@link #createDiff} for usage. */
static final Long ORDER_ID_SENTINEL = Long.MIN_VALUE;
private final GcsClient gcsClient;
@Inject
BsaDiffCreator(GcsClient gcsClient) {
this.gcsClient = gcsClient;
}
private <K, V extends Comparable> Multimap<K, V> listBackedMultiMap() {
return newListMultimap(newHashMap(), Lists::newArrayList);
}
BsaDiff createDiff(DownloadSchedule schedule, IdnChecker idnChecker) {
String currentJobName = schedule.jobName();
Optional<String> previousJobName = schedule.latestCompleted().map(CompletedJob::jobName);
/*
* Memory usage is a concern when creating a diff, when the newest download needs to be held in
* memory in its entirety. The top-grade AppEngine VM has 3GB of memory, leaving less than 1.5GB
* to application memory footprint after subtracting overheads due to copying garbage collection
* and non-heap data etc. Assuming 400K labels, each of which on average included in 5 orders,
* the memory footprint is at least 300MB when loaded into a Hashset-backed Multimap (64-bit
* JVM, with 12-byte object header, 16-byte array header, and 16-byte alignment).
*
* <p>The memory footprint can be reduced in two ways, by using a canonical instance for each
* order ID value, and by using a ArrayList-backed Multimap. Together they reduce memory size to
* well below 100MB for the scenario above.
*
* <p>We need to watch out for the download sizes even after the migration to GKE. However, at
* that point we will have a wider selection of hardware.
*
* <p>Beam pipeline is not a good option. It has to be launched as a separate, asynchronous job,
* and there is no guaranteed limit to launch delay. Both issues would increase code complexity.
*/
Canonicals<Long> canonicals = new Canonicals<>();
try (Stream<Line> currentStream = loadBlockLists(currentJobName);
Stream<Line> previousStream =
previousJobName.map(this::loadBlockLists).orElseGet(Stream::of)) {
/*
* Load current label/order pairs into a multimap, which will contain both new labels and
* those that stay on when processing is done.
*/
Multimap<String, Long> newAndRemaining =
currentStream
.map(line -> line.labelOrderPairs(canonicals))
.flatMap(x -> x)
.collect(
toMultimap(
LabelOrderPair::label, LabelOrderPair::orderId, this::listBackedMultiMap));
Multimap<String, Long> deleted =
previousStream
.map(
line -> {
// Mark labels that exist in both downloads with the SENTINEL id. This helps
// distinguish existing label with new order from new labels.
if (newAndRemaining.containsKey(line.label())
&& !newAndRemaining.containsEntry(line.label(), ORDER_ID_SENTINEL)) {
newAndRemaining.put(line.label(), ORDER_ID_SENTINEL);
}
return line;
})
.map(line -> line.labelOrderPairs(canonicals))
.flatMap(x -> x)
.filter(kv -> !newAndRemaining.remove(kv.label(), kv.orderId()))
.collect(
toMultimap(
LabelOrderPair::label, LabelOrderPair::orderId, this::listBackedMultiMap));
/*
* Labels in `newAndRemaining`:
*
* <ul>
* <li>Mapped to `sentinel` only: Labels without change, ignore
* <li>Mapped to `sentinel` and some orders: Existing labels with new order mapping. Those
* orders are new orders.
* <li>Mapped to some orders but not `sentinel`: New labels and new orders.
* </ul>
*
* <p>The `deleted` map has
*
* <ul>
* <li>Deleted labels: the keyset of deleted minus the keyset of the newAndRemaining
* <li>Deleted orders: the union of values.
* </ul>
*/
return new BsaDiff(
ImmutableMultimap.copyOf(newAndRemaining), ImmutableMultimap.copyOf(deleted), idnChecker);
}
}
Stream<Line> loadBlockLists(String jobName) {
return Stream.of(BlockListType.values())
.map(blockList -> gcsClient.readBlockList(jobName, blockList))
.flatMap(x -> x)
.filter(line -> !line.startsWith(BSA_CSV_HEADER))
.map(BsaDiffCreator::parseLine);
}
static Line parseLine(String line) {
List<String> columns = LINE_SPLITTER.splitToList(line);
checkArgument(columns.size() == 2, "Invalid line: [%s]", line);
checkArgument(!Strings.isNullOrEmpty(columns.get(0)), "Missing label in line: [%s]", line);
try {
ImmutableList<Long> orderIds =
ORDER_SPLITTER
.splitToStream(columns.get(1))
.map(Long::valueOf)
.collect(toImmutableList());
checkArgument(!orderIds.isEmpty(), "Missing orders in line: [%s]", line);
checkArgument(
!orderIds.contains(ORDER_ID_SENTINEL), "Invalid order id %s", ORDER_ID_SENTINEL);
return Line.of(columns.get(0), orderIds);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(line, e);
}
}
static class BsaDiff {
private final ImmutableMultimap<String, Long> newAndRemaining;
private final ImmutableMultimap<String, Long> deleted;
private final IdnChecker idnChecker;
BsaDiff(
ImmutableMultimap<String, Long> newAndRemaining,
ImmutableMultimap<String, Long> deleted,
IdnChecker idnChecker) {
this.newAndRemaining = newAndRemaining;
this.deleted = deleted;
this.idnChecker = idnChecker;
}
Stream<BlockOrder> getOrders() {
return Stream.concat(
newAndRemaining.values().stream()
.filter(value -> !Objects.equals(ORDER_ID_SENTINEL, value))
.distinct()
.map(id -> BlockOrder.of(id, OrderType.CREATE)),
deleted.values().stream().distinct().map(id -> BlockOrder.of(id, OrderType.DELETE)));
}
Stream<BlockLabel> getLabels() {
return Stream.of(
newAndRemaining.asMap().entrySet().stream()
.filter(e -> e.getValue().size() > 1 || !e.getValue().contains(ORDER_ID_SENTINEL))
.filter(entry -> entry.getValue().contains(ORDER_ID_SENTINEL))
.map(
entry ->
BlockLabel.of(
entry.getKey(),
LabelType.NEW_ORDER_ASSOCIATION,
getAllValidIdnNames(entry.getKey()))),
newAndRemaining.asMap().entrySet().stream()
.filter(e -> e.getValue().size() > 1 || !e.getValue().contains(ORDER_ID_SENTINEL))
.filter(entry -> !entry.getValue().contains(ORDER_ID_SENTINEL))
.map(
entry ->
BlockLabel.of(
entry.getKey(),
LabelType.CREATE,
getAllValidIdnNames(entry.getKey()))),
Sets.difference(deleted.keySet(), newAndRemaining.keySet()).stream()
.map(label -> BlockLabel.of(label, LabelType.DELETE, getAllValidIdnNames(label))))
.flatMap(x -> x);
}
ImmutableSet<String> getAllValidIdnNames(String label) {
return idnChecker.getAllValidIdns(label).stream()
.map(IdnTableEnum::name)
.collect(toImmutableSet());
}
}
static class Canonicals<T> {
private final HashMap<T, T> cache;
Canonicals() {
cache = Maps.newHashMap();
}
T get(T value) {
cache.putIfAbsent(value, value);
return cache.get(value);
}
}
@AutoValue
abstract static class LabelOrderPair {
abstract String label();
abstract Long orderId();
static LabelOrderPair of(String key, Long value) {
return new AutoValue_BsaDiffCreator_LabelOrderPair(key, value);
}
}
@AutoValue
abstract static class Line {
abstract String label();
abstract ImmutableList<Long> orderIds();
Stream<LabelOrderPair> labelOrderPairs(Canonicals<Long> canonicals) {
return orderIds().stream().map(id -> LabelOrderPair.of(label(), canonicals.get(id)));
}
static Line of(String label, ImmutableList<Long> orderIds) {
return new AutoValue_BsaDiffCreator_Line(label, orderIds);
}
}
}

View File

@@ -1,238 +0,0 @@
// Copyright 2023 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.bsa;
import static google.registry.bsa.BlockListType.BLOCK;
import static google.registry.bsa.BlockListType.BLOCK_PLUS;
import static google.registry.bsa.api.JsonSerializations.toCompletedOrdersReport;
import static google.registry.bsa.api.JsonSerializations.toInProgressOrdersReport;
import static google.registry.bsa.api.JsonSerializations.toUnblockableDomainsReport;
import static google.registry.bsa.persistence.LabelDiffUpdates.applyLabelDiff;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.BatchedStreams.toBatches;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import dagger.Lazy;
import google.registry.bsa.BlockListFetcher.LazyBlockList;
import google.registry.bsa.BsaDiffCreator.BsaDiff;
import google.registry.bsa.api.BlockLabel;
import google.registry.bsa.api.BlockOrder;
import google.registry.bsa.api.BsaReportSender;
import google.registry.bsa.api.UnblockableDomain;
import google.registry.bsa.persistence.DownloadSchedule;
import google.registry.bsa.persistence.DownloadScheduler;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.tld.Tlds;
import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
@Action(
service = Action.Service.BSA,
path = BsaDownloadAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_API_ADMIN)
public class BsaDownloadAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final String PATH = "/_dr/task/bsaDownload";
private final DownloadScheduler downloadScheduler;
private final BlockListFetcher blockListFetcher;
private final BsaDiffCreator diffCreator;
private final BsaReportSender bsaReportSender;
private final GcsClient gcsClient;
private final Lazy<IdnChecker> lazyIdnChecker;
private final BsaLock bsaLock;
private final Clock clock;
private final int transactionBatchSize;
private final Response response;
@Inject
BsaDownloadAction(
DownloadScheduler downloadScheduler,
BlockListFetcher blockListFetcher,
BsaDiffCreator diffCreator,
BsaReportSender bsaReportSender,
GcsClient gcsClient,
Lazy<IdnChecker> lazyIdnChecker,
BsaLock bsaLock,
Clock clock,
@Config("bsaTxnBatchSize") int transactionBatchSize,
Response response) {
this.downloadScheduler = downloadScheduler;
this.blockListFetcher = blockListFetcher;
this.diffCreator = diffCreator;
this.bsaReportSender = bsaReportSender;
this.gcsClient = gcsClient;
this.lazyIdnChecker = lazyIdnChecker;
this.bsaLock = bsaLock;
this.clock = clock;
this.transactionBatchSize = transactionBatchSize;
this.response = response;
}
@Override
public void run() {
try {
if (!bsaLock.executeWithLock(this::runWithinLock)) {
logger.atInfo().log("Job is being executed by another worker.");
}
} catch (Throwable throwable) {
// TODO(12/31/2023): consider sending an alert email.
// TODO: if unretriable errors, log at severe and send email.
logger.atWarning().withCause(throwable).log("Failed to update block lists.");
}
// Always return OK. Let the next cron job retry.
response.setStatus(SC_OK);
}
Void runWithinLock() {
// Cannot enroll new TLDs after download starts. This may change if b/309175410 is fixed.
if (!Tlds.hasActiveBsaEnrollment(clock.nowUtc())) {
logger.atInfo().log("No TLDs enrolled with BSA. Quitting.");
return null;
}
Optional<DownloadSchedule> scheduleOptional = downloadScheduler.schedule();
if (scheduleOptional.isEmpty()) {
logger.atInfo().log("Nothing to do.");
return null;
}
BsaDiff diff = null;
DownloadSchedule schedule = scheduleOptional.get();
switch (schedule.stage()) {
case DOWNLOAD_BLOCK_LISTS:
try (LazyBlockList block = blockListFetcher.fetch(BLOCK);
LazyBlockList blockPlus = blockListFetcher.fetch(BLOCK_PLUS)) {
ImmutableMap<BlockListType, String> fetchedChecksums =
ImmutableMap.of(BLOCK, block.checksum(), BLOCK_PLUS, blockPlus.checksum());
ImmutableMap<BlockListType, String> prevChecksums =
schedule
.latestCompleted()
.map(DownloadSchedule.CompletedJob::checksums)
.orElseGet(ImmutableMap::of);
boolean checksumsMatch = Objects.equals(fetchedChecksums, prevChecksums);
if (!schedule.alwaysDownload() && checksumsMatch) {
logger.atInfo().log(
"Skipping download b/c block list checksums have not changed: [%s]",
fetchedChecksums);
schedule.updateJobStage(DownloadStage.NOP, fetchedChecksums);
return null;
} else if (checksumsMatch) {
logger.atInfo().log(
"Checksums match but download anyway: elapsed time since last download exceeds"
+ " configured limit.");
}
// When downloading, always fetch both lists so that whole data set is in one GCS folder.
ImmutableMap<BlockListType, String> actualChecksum =
gcsClient.saveAndChecksumBlockList(
schedule.jobName(), ImmutableList.of(block, blockPlus));
if (!Objects.equals(fetchedChecksums, actualChecksum)) {
logger.atSevere().log(
"Inlined checksums do not match those calculated by us. Theirs: [%s]; ours: [%s]",
fetchedChecksums, actualChecksum);
schedule.updateJobStage(DownloadStage.CHECKSUMS_DO_NOT_MATCH, fetchedChecksums);
// TODO(01/15/24): add email alert.
return null;
}
schedule.updateJobStage(DownloadStage.MAKE_ORDER_AND_LABEL_DIFF, actualChecksum);
}
// Fall through
case MAKE_ORDER_AND_LABEL_DIFF:
diff = diffCreator.createDiff(schedule, lazyIdnChecker.get());
// TODO(weiminyu): log the diff stats
gcsClient.writeOrderDiffs(schedule.jobName(), diff.getOrders());
gcsClient.writeLabelDiffs(schedule.jobName(), diff.getLabels());
schedule.updateJobStage(DownloadStage.APPLY_ORDER_AND_LABEL_DIFF);
// Fall through
case APPLY_ORDER_AND_LABEL_DIFF:
try (Stream<BlockLabel> labels =
diff != null ? diff.getLabels() : gcsClient.readLabelDiffs(schedule.jobName())) {
Stream<ImmutableList<BlockLabel>> batches = toBatches(labels, transactionBatchSize);
gcsClient.writeUnblockableDomains(
schedule.jobName(),
batches
.map(
batch ->
applyLabelDiff(batch, lazyIdnChecker.get(), schedule, clock.nowUtc()))
.flatMap(ImmutableList::stream));
}
schedule.updateJobStage(DownloadStage.REPORT_START_OF_ORDER_PROCESSING);
// Fall through
case REPORT_START_OF_ORDER_PROCESSING:
try (Stream<BlockOrder> orders = gcsClient.readOrderDiffs(schedule.jobName())) {
// We expect that all order instances and the json string can fit in memory.
Optional<String> report = toInProgressOrdersReport(orders);
if (report.isPresent()) {
// Log report data
gcsClient.logInProgressOrderReport(
schedule.jobName(), BsaStringUtils.LINE_SPLITTER.splitToStream(report.get()));
bsaReportSender.sendOrderStatusReport(report.get());
} else {
logger.atInfo().log("No new or deleted orders in this round.");
}
}
schedule.updateJobStage(DownloadStage.UPLOAD_UNBLOCKABLE_DOMAINS_FOR_NEW_ORDERS);
// Fall through
case UPLOAD_UNBLOCKABLE_DOMAINS_FOR_NEW_ORDERS:
try (Stream<UnblockableDomain> unblockables =
gcsClient.readUnblockableDomains(schedule.jobName())) {
/* The number of unblockable domains may be huge in theory (label x ~50 tlds), but in
* practice should be relatively small (tens of thousands?). Batches can be introduced
* if size becomes a problem.
*/
Optional<String> report = toUnblockableDomainsReport(unblockables);
if (report.isPresent()) {
gcsClient.logAddedUnblockableDomainsReport(
schedule.jobName(), BsaStringUtils.LINE_SPLITTER.splitToStream(report.get()));
// During downloads, unblockable domains are only added, not removed.
bsaReportSender.addUnblockableDomainsUpdates(report.get());
} else {
logger.atInfo().log("No changes in the set of unblockable domains in this round.");
}
}
schedule.updateJobStage(DownloadStage.REPORT_END_OF_ORDER_PROCESSING);
// Fall through
case REPORT_END_OF_ORDER_PROCESSING:
try (Stream<BlockOrder> orders = gcsClient.readOrderDiffs(schedule.jobName())) {
// Orders are expected to be few, so the report can be kept in memory.
Optional<String> report = toCompletedOrdersReport(orders);
if (report.isPresent()) {
gcsClient.logCompletedOrderReport(
schedule.jobName(), BsaStringUtils.LINE_SPLITTER.splitToStream(report.get()));
bsaReportSender.sendOrderStatusReport(report.get());
}
}
schedule.updateJobStage(DownloadStage.DONE);
return null;
case DONE:
case NOP:
case CHECKSUMS_DO_NOT_MATCH:
logger.atWarning().log("Unexpectedly reached the %s stage.", schedule.stage());
break;
}
return null;
}
}

View File

@@ -1,41 +0,0 @@
// Copyright 2024 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.bsa;
import google.registry.config.RegistryConfig.Config;
import google.registry.groups.GmailClient;
import google.registry.util.EmailMessage;
import javax.inject.Inject;
import javax.mail.internet.InternetAddress;
/** Sends BSA-related email notifications. */
class BsaEmailSender {
private final InternetAddress alertRecipientAddress;
private final GmailClient gmailClient;
@Inject
BsaEmailSender(
GmailClient gmailClient,
@Config("newAlertRecipientEmailAddress") InternetAddress alertRecipientAddress) {
this.alertRecipientAddress = alertRecipientAddress;
this.gmailClient = gmailClient;
}
/** Sends an email to the configured alert recipient. */
void sendNotification(String subject, String body) {
this.gmailClient.sendEmail(EmailMessage.create(subject, body, alertRecipientAddress));
}
}

View File

@@ -1,187 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static google.registry.bsa.BsaStringUtils.LINE_SPLITTER;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import google.registry.bsa.api.BsaReportSender;
import google.registry.bsa.api.JsonSerializations;
import google.registry.bsa.api.UnblockableDomainChange;
import google.registry.bsa.persistence.DomainsRefresher;
import google.registry.bsa.persistence.RefreshSchedule;
import google.registry.bsa.persistence.RefreshScheduler;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.tld.Tlds;
import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.BatchedStreams;
import google.registry.util.Clock;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.joda.time.Duration;
@Action(
service = Action.Service.BSA,
path = BsaRefreshAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_API_ADMIN)
public class BsaRefreshAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final String PATH = "/_dr/task/bsaRefresh";
private final RefreshScheduler scheduler;
private final GcsClient gcsClient;
private final BsaReportSender bsaReportSender;
private final int transactionBatchSize;
private final Duration domainCreateTxnCommitTimeLag;
private final BsaEmailSender emailSender;
private final BsaLock bsaLock;
private final Clock clock;
private final Response response;
@Inject
BsaRefreshAction(
RefreshScheduler scheduler,
GcsClient gcsClient,
BsaReportSender bsaReportSender,
@Config("bsaTxnBatchSize") int transactionBatchSize,
@Config("domainCreateTxnCommitTimeLag") Duration domainCreateTxnCommitTimeLag,
BsaEmailSender emailSender,
BsaLock bsaLock,
Clock clock,
Response response) {
this.scheduler = scheduler;
this.gcsClient = gcsClient;
this.bsaReportSender = bsaReportSender;
this.transactionBatchSize = transactionBatchSize;
this.domainCreateTxnCommitTimeLag = domainCreateTxnCommitTimeLag;
this.emailSender = emailSender;
this.bsaLock = bsaLock;
this.clock = clock;
this.response = response;
}
@Override
public void run() {
try {
if (!bsaLock.executeWithLock(this::runWithinLock)) {
String message = "BSA refresh did not run: another BSA related task is running";
logger.atInfo().log("%s.", message);
emailSender.sendNotification(message, /* body= */ "");
} else {
emailSender.sendNotification("BSA refreshed successfully", "");
}
} catch (Throwable throwable) {
logger.atWarning().withCause(throwable).log("Failed to refresh BSA data.");
emailSender.sendNotification("BSA refresh aborted", getStackTraceAsString(throwable));
}
// Always return OK. No need to use a retrier on `runWithinLock`. Its individual steps are
// implicitly retried. If action fails, the next cron will continue at checkpoint.
response.setStatus(SC_OK);
}
/** Executes the refresh action while holding the BSA lock. */
Void runWithinLock() {
// Cannot enroll new TLDs after download starts. This may change if b/309175410 is fixed.
if (!Tlds.hasActiveBsaEnrollment(clock.nowUtc())) {
logger.atInfo().log("No TLDs enrolled with BSA. Quitting.");
return null;
}
Optional<RefreshSchedule> maybeSchedule = scheduler.schedule();
if (maybeSchedule.isEmpty()) {
logger.atInfo().log("No completed downloads yet. Exiting.");
return null;
}
RefreshSchedule schedule = maybeSchedule.get();
DomainsRefresher refresher =
new DomainsRefresher(
schedule.prevRefreshTime(),
clock.nowUtc(),
domainCreateTxnCommitTimeLag,
transactionBatchSize);
switch (schedule.stage()) {
case CHECK_FOR_CHANGES:
ImmutableList<UnblockableDomainChange> blockabilityChanges =
refresher.checkForBlockabilityChanges();
if (blockabilityChanges.isEmpty()) {
logger.atInfo().log("No change to Unblockable domains found.");
schedule.updateJobStage(RefreshStage.DONE);
return null;
}
gcsClient.writeRefreshChanges(schedule.jobName(), blockabilityChanges.stream());
schedule.updateJobStage(RefreshStage.APPLY_CHANGES);
// Fall through
case APPLY_CHANGES:
try (Stream<UnblockableDomainChange> changes =
gcsClient.readRefreshChanges(schedule.jobName())) {
BatchedStreams.toBatches(changes, 500).forEach(refresher::applyUnblockableChanges);
}
schedule.updateJobStage(RefreshStage.UPLOAD_REMOVALS);
// Fall through
case UPLOAD_REMOVALS:
try (Stream<UnblockableDomainChange> changes =
gcsClient.readRefreshChanges(schedule.jobName())) {
// Unblockables with changes in REASON are removed then added back. That is why they are
// included in this stage.
Optional<String> report =
JsonSerializations.toUnblockableDomainsRemovalReport(
changes
.filter(UnblockableDomainChange::isChangeOrDelete)
.map(UnblockableDomainChange::domainName));
if (report.isPresent()) {
gcsClient.logRemovedUnblockableDomainsReport(
schedule.jobName(), LINE_SPLITTER.splitToStream(report.get()));
bsaReportSender.removeUnblockableDomainsUpdates(report.get());
} else {
logger.atInfo().log("No Unblockable domains to remove.");
}
}
schedule.updateJobStage(RefreshStage.UPLOAD_ADDITIONS);
// Fall through
case UPLOAD_ADDITIONS:
try (Stream<UnblockableDomainChange> changes =
gcsClient.readRefreshChanges(schedule.jobName())) {
Optional<String> report =
JsonSerializations.toUnblockableDomainsReport(
changes
.filter(UnblockableDomainChange::isNewOrChange)
.map(UnblockableDomainChange::newValue));
if (report.isPresent()) {
gcsClient.logAddedUnblockableDomainsReport(
schedule.jobName(), LINE_SPLITTER.splitToStream(report.get()));
bsaReportSender.addUnblockableDomainsUpdates(report.get());
} else {
logger.atInfo().log("No new Unblockable domains to add.");
}
}
schedule.updateJobStage(RefreshStage.DONE);
break;
case DONE:
logger.atInfo().log("Unexpectedly reaching the `DONE` stage.");
break;
}
return null;
}
}

View File

@@ -1,45 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.util.List;
/** Helpers for domain name manipulation and string serialization of Java objects. */
public class BsaStringUtils {
public static final Joiner DOMAIN_JOINER = Joiner.on('.');
public static final Joiner PROPERTY_JOINER = Joiner.on(',');
public static final Splitter DOMAIN_SPLITTER = Splitter.on('.');
public static final Splitter PROPERTY_SPLITTER = Splitter.on(',');
public static final Splitter LINE_SPLITTER = Splitter.on('\n');
public static String getLabelInDomain(String domainName) {
List<String> parts = DOMAIN_SPLITTER.splitToList(domainName);
checkArgument(!parts.isEmpty(), "Not a valid domain: [%s]", domainName);
return parts.get(0);
}
public static String getTldInDomain(String domainName) {
List<String> parts = DOMAIN_SPLITTER.splitToList(domainName);
checkArgument(parts.size() == 2, "Not a valid domain: [%s]", domainName);
return parts.get(1);
}
private BsaStringUtils() {}
}

View File

@@ -1,55 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.base.Verify.verify;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import google.registry.persistence.transaction.TransactionManager.ThrowingRunnable;
import java.util.concurrent.Callable;
/**
* Helpers for executing JPA transactions for BSA processing.
*
* <p>All mutating transactions for BSA are executed at the {@code TRANSACTION_REPEATABLE_READ}
* level since the global {@link BsaLock} ensures there is a single writer at any time.
*
* <p>All domain and label queries can use the replica since all processing are snapshot based.
*/
public final class BsaTransactions {
@CanIgnoreReturnValue
public static <T> T bsaTransact(Callable<T> work) {
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
return tm().transact(TRANSACTION_REPEATABLE_READ, work);
}
public static void bsaTransact(ThrowingRunnable work) {
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
tm().transact(TRANSACTION_REPEATABLE_READ, work);
}
@CanIgnoreReturnValue
public static <T> T bsaQuery(Callable<T> work) {
verify(!tm().inTransaction(), "May only be used for top-level transactions.");
// TRANSACTION_REPEATABLE_READ is default on replica.
return replicaTm().transact(work);
}
private BsaTransactions() {}
}

View File

@@ -1,187 +0,0 @@
// Copyright 2024 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.bsa;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static google.registry.bsa.BsaTransactions.bsaQuery;
import static google.registry.bsa.persistence.Queries.batchReadBsaLabelText;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.flogger.FluentLogger;
import google.registry.bsa.persistence.DownloadScheduler;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
/** Validates the BSA data in the database against the most recent block lists. */
@Action(
service = Action.Service.BSA,
path = BsaValidateAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_API_ADMIN)
public class BsaValidateAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
static final String PATH = "/_dr/task/bsaValidate";
private final GcsClient gcsClient;
private final IdnChecker idnChecker;
private final BsaEmailSender emailSender;
private final int transactionBatchSize;
private final BsaLock bsaLock;
private final Response response;
@Inject
BsaValidateAction(
GcsClient gcsClient,
IdnChecker idnChecker,
BsaEmailSender emailSender,
@Config("bsaTxnBatchSize") int transactionBatchSize,
BsaLock bsaLock,
Response response) {
this.gcsClient = gcsClient;
this.idnChecker = idnChecker;
this.emailSender = emailSender;
this.transactionBatchSize = transactionBatchSize;
this.bsaLock = bsaLock;
this.response = response;
}
@Override
public void run() {
try {
if (!bsaLock.executeWithLock(this::runWithinLock)) {
String message = "BSA validation did not run: another BSA related task is running";
logger.atInfo().log("%s.", message);
emailSender.sendNotification(message, /* body= */ "");
}
} catch (Throwable throwable) {
logger.atWarning().withCause(throwable).log("Failed to validate block lists.");
emailSender.sendNotification("BSA validation aborted", getStackTraceAsString(throwable));
}
// Always return OK. No need to retry since all queries and GCS accesses are already
// implicitly retried.
response.setStatus(SC_OK);
}
/** Executes the validation action while holding the BSA lock. */
Void runWithinLock() {
Optional<String> downloadJobName =
bsaQuery(DownloadScheduler::fetchMostRecentDownloadJobIdIfCompleted);
if (downloadJobName.isEmpty()) {
logger.atInfo().log("Cannot validate: block list downloads not found.");
emailSender.sendNotification(
"BSA validation does not run: block list downloads not found", "");
return null;
}
logger.atInfo().log("Validating BSA with latest download: %s", downloadJobName.get());
ImmutableList.Builder<String> errorsBuilder = new ImmutableList.Builder<>();
errorsBuilder.addAll(checkBsaLabels(downloadJobName.get()));
ImmutableList<String> errors = errorsBuilder.build();
String resultSummary =
errors.isEmpty()
? "BSA validation completed: no errors found"
: "BSA validation completed with errors";
emailValidationResults(resultSummary, downloadJobName.get(), errors);
logger.atInfo().log("Finished validating BSA with latest download: %s", downloadJobName.get());
return null;
}
void emailValidationResults(String subject, String jobName, ImmutableList<String> results) {
String body =
String.format("Most recent download is %s.\n\n", jobName) + Joiner.on('\n').join(results);
emailSender.sendNotification(subject, body);
}
ImmutableList<String> checkBsaLabels(String jobName) {
ImmutableSet<String> downloadedLabels = fetchDownloadedLabels(jobName);
ImmutableSet<String> persistedLabels = fetchPersistedLabels(transactionBatchSize);
ImmutableList.Builder<String> errors = new ImmutableList.Builder<>();
int nErrorExamples = 10;
SetView<String> missingLabels = Sets.difference(downloadedLabels, persistedLabels);
if (!missingLabels.isEmpty()) {
String examples = Joiner.on(',').join(Iterables.limit(missingLabels, nErrorExamples));
String errorMessage =
String.format(
"Found %d missing labels in the DB. Examples: [%s]", missingLabels.size(), examples);
logger.atInfo().log(errorMessage);
errors.add(errorMessage);
}
SetView<String> unexpectedLabels = Sets.difference(persistedLabels, downloadedLabels);
if (!unexpectedLabels.isEmpty()) {
String examples = Joiner.on(',').join(Iterables.limit(unexpectedLabels, nErrorExamples));
String errorMessage =
String.format(
"Found %d unexpected labels in the DB. Examples: [%s]",
unexpectedLabels.size(), examples);
logger.atInfo().log(errorMessage);
errors.add(errorMessage);
}
return errors.build();
}
/** Returns unique labels across all block lists in the download specified by {@code jobName}. */
ImmutableSet<String> fetchDownloadedLabels(String jobName) {
ImmutableSet.Builder<String> labelsBuilder = new ImmutableSet.Builder<>();
for (BlockListType blockListType : BlockListType.values()) {
try (Stream<String> lines = gcsClient.readBlockList(jobName, blockListType)) {
lines
.skip(1)
.map(BsaValidateAction::parseBlockListLine)
.filter(label -> !idnChecker.getAllValidIdns(label).isEmpty())
.forEach(labelsBuilder::add);
}
}
return labelsBuilder.build();
}
ImmutableSet<String> fetchPersistedLabels(int batchSize) {
ImmutableSet.Builder<String> labelsBuilder = new ImmutableSet.Builder<>();
ImmutableList<String> batch;
Optional<String> lastRead = Optional.empty();
do {
batch = batchReadBsaLabelText(lastRead, batchSize);
batch.forEach(labelsBuilder::add);
if (!batch.isEmpty()) {
lastRead = Optional.of(Iterables.getLast(batch));
}
} while (batch.size() == batchSize);
return labelsBuilder.build();
}
static String parseBlockListLine(String line) {
int firstComma = line.indexOf(',');
checkArgument(firstComma > 0, "Invalid block list line: %s", line);
return line.substring(0, firstComma);
}
}

View File

@@ -14,32 +14,23 @@
package google.registry.bsa;
import google.registry.bsa.api.BlockLabel;
import google.registry.bsa.api.BlockOrder;
/** The processing stages of a download. */
public enum DownloadStage {
/** Downloads BSA block list files. */
DOWNLOAD_BLOCK_LISTS,
/**
* Generates block list diffs against the previous download. The diffs consist of a stream of
* {@link BlockOrder orders} and a stream of {@link BlockLabel labels}.
*/
MAKE_ORDER_AND_LABEL_DIFF,
/** Applies the diffs to the database. */
APPLY_ORDER_AND_LABEL_DIFF,
DOWNLOAD,
/** Generates block list diffs with the previous download. */
MAKE_DIFF,
/** Applies the label diffs to the database tables. */
APPLY_DIFF,
/**
* Makes a REST API call to BSA endpoint, declaring that processing starts for new orders in the
* diffs.
*/
REPORT_START_OF_ORDER_PROCESSING,
/**
* Makes a REST API call to BSA endpoint, uploading unblockable domains that match labels in the
* diff.
*/
UPLOAD_UNBLOCKABLE_DOMAINS_FOR_NEW_ORDERS,
START_UPLOADING,
/** Makes a REST API call to BSA endpoint, sending the domains that cannot be blocked. */
UPLOAD_DOMAINS_IN_USE,
/** Makes a REST API call to BSA endpoint, declaring the completion of order processing. */
REPORT_END_OF_ORDER_PROCESSING,
FINISH_UPLOADING,
/** The terminal stage after processing succeeds. */
DONE,
/**
@@ -51,5 +42,5 @@ public enum DownloadStage {
* The terminal stage indicating that the downloads are not processed because their BSA-generated
* checksums do not match those calculated by us.
*/
CHECKSUMS_DO_NOT_MATCH;
CHECKSUMS_NOT_MATCH;
}

View File

@@ -1,229 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.io.BaseEncoding.base16;
import com.google.cloud.storage.BlobId;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.bsa.BlockListFetcher.LazyBlockList;
import google.registry.bsa.api.BlockLabel;
import google.registry.bsa.api.BlockOrder;
import google.registry.bsa.api.UnblockableDomain;
import google.registry.bsa.api.UnblockableDomainChange;
import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.stream.Stream;
import javax.inject.Inject;
/** Stores and accesses BSA-related data, including original downloads and processed data. */
public class GcsClient {
// Intermediate data files:
static final String LABELS_DIFF_FILE = "labels_diff.csv";
static final String ORDERS_DIFF_FILE = "orders_diff.csv";
static final String UNBLOCKABLE_DOMAINS_FILE = "unblockable_domains.csv";
static final String REFRESHED_UNBLOCKABLE_DOMAINS_FILE = "refreshed_unblockable_domains.csv";
// Logged report data sent to BSA.
static final String IN_PROGRESS_ORDERS_REPORT = "in_progress_orders.json";
static final String COMPLETED_ORDERS_REPORT = "completed_orders.json";
static final String ADDED_UNBLOCKABLE_DOMAINS_REPORT = "added_unblockable_domains.json";
static final String REMOVED_UNBLOCKABLE_DOMAINS_REPORT = "removed_unblockable_domains.json";
private final GcsUtils gcsUtils;
private final String bucketName;
private final String checksumAlgorithm;
@Inject
GcsClient(
GcsUtils gcsUtils,
@Config("bsaGcsBucket") String bucketName,
@Config("bsaChecksumAlgorithm") String checksumAlgorithm) {
this.gcsUtils = gcsUtils;
this.bucketName = bucketName;
this.checksumAlgorithm = checksumAlgorithm;
}
static String getBlockListFileName(BlockListType blockListType) {
return blockListType.name() + ".csv";
}
ImmutableMap<BlockListType, String> saveAndChecksumBlockList(
String jobName, ImmutableList<LazyBlockList> blockLists) {
// Downloading sequentially, since one is expected to be much smaller than the other.
return blockLists.stream()
.collect(
ImmutableMap.toImmutableMap(
LazyBlockList::getName, blockList -> saveAndChecksumBlockList(jobName, blockList)));
}
private String saveAndChecksumBlockList(String jobName, LazyBlockList blockList) {
BlobId blobId = getBlobId(jobName, getBlockListFileName(blockList.getName()));
try (BufferedOutputStream gcsWriter =
new BufferedOutputStream(gcsUtils.openOutputStream(blobId))) {
MessageDigest messageDigest = MessageDigest.getInstance(checksumAlgorithm);
blockList.consumeAll(
(byteArray, length) -> {
try {
gcsWriter.write(byteArray, 0, length);
} catch (IOException e) {
throw new RuntimeException(e);
}
messageDigest.update(byteArray, 0, length);
});
return base16().lowerCase().encode(messageDigest.digest());
} catch (IOException | NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
private static void writeWithNewline(BufferedWriter writer, String line) {
try {
writer.write(line);
if (!line.endsWith("\n")) {
writer.write('\n');
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Stream<String> readBlockList(String jobName, BlockListType blockListType) {
return readStream(getBlobId(jobName, getBlockListFileName(blockListType)));
}
Stream<BlockOrder> readOrderDiffs(String jobName) {
BlobId blobId = getBlobId(jobName, ORDERS_DIFF_FILE);
return readStream(blobId).map(BlockOrder::deserialize);
}
void writeOrderDiffs(String jobName, Stream<BlockOrder> orders) {
BlobId blobId = getBlobId(jobName, ORDERS_DIFF_FILE);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
orders.map(BlockOrder::serialize).forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Stream<BlockLabel> readLabelDiffs(String jobName) {
BlobId blobId = getBlobId(jobName, LABELS_DIFF_FILE);
return readStream(blobId).map(BlockLabel::deserialize);
}
void writeLabelDiffs(String jobName, Stream<BlockLabel> labels) {
BlobId blobId = getBlobId(jobName, LABELS_DIFF_FILE);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
labels.map(BlockLabel::serialize).forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Stream<UnblockableDomain> readUnblockableDomains(String jobName) {
BlobId blobId = getBlobId(jobName, UNBLOCKABLE_DOMAINS_FILE);
return readStream(blobId).map(UnblockableDomain::deserialize);
}
void writeUnblockableDomains(String jobName, Stream<UnblockableDomain> unblockables) {
BlobId blobId = getBlobId(jobName, UNBLOCKABLE_DOMAINS_FILE);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
unblockables
.map(UnblockableDomain::serialize)
.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Stream<UnblockableDomainChange> readRefreshChanges(String jobName) {
BlobId blobId = getBlobId(jobName, REFRESHED_UNBLOCKABLE_DOMAINS_FILE);
return readStream(blobId).map(UnblockableDomainChange::deserialize);
}
void writeRefreshChanges(String jobName, Stream<UnblockableDomainChange> changes) {
BlobId blobId = getBlobId(jobName, REFRESHED_UNBLOCKABLE_DOMAINS_FILE);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
changes
.map(UnblockableDomainChange::serialize)
.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void logInProgressOrderReport(String jobName, Stream<String> lines) {
BlobId blobId = getBlobId(jobName, IN_PROGRESS_ORDERS_REPORT);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
lines.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void logCompletedOrderReport(String jobName, Stream<String> lines) {
BlobId blobId = getBlobId(jobName, COMPLETED_ORDERS_REPORT);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
lines.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void logAddedUnblockableDomainsReport(String jobName, Stream<String> lines) {
BlobId blobId = getBlobId(jobName, ADDED_UNBLOCKABLE_DOMAINS_REPORT);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
lines.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void logRemovedUnblockableDomainsReport(String jobName, Stream<String> lines) {
BlobId blobId = getBlobId(jobName, REMOVED_UNBLOCKABLE_DOMAINS_REPORT);
try (BufferedWriter gcsWriter = getWriter(blobId)) {
lines.forEach(line -> writeWithNewline(gcsWriter, line));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
BlobId getBlobId(String folder, String name) {
return BlobId.of(bucketName, String.format("%s/%s", folder, name));
}
Stream<String> readStream(BlobId blobId) {
return new BufferedReader(
new InputStreamReader(gcsUtils.openInputStream(blobId), StandardCharsets.UTF_8))
.lines();
}
BufferedWriter getWriter(BlobId blobId) {
return new BufferedWriter(
new OutputStreamWriter(gcsUtils.openOutputStream(blobId), StandardCharsets.UTF_8));
}
}

View File

@@ -16,12 +16,13 @@ package google.registry.bsa;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Maps.transformValues;
import static google.registry.model.tld.Tld.isEnrolledWithBsa;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
@@ -49,8 +50,16 @@ public class IdnChecker {
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
}
// TODO(11/30/2023): Remove below when new Tld schema is deployed and the `getBsaEnrollStartTime`
// method is no longer hardcoded.
@VisibleForTesting
IdnChecker(ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> idnToTlds) {
this.idnToTlds = idnToTlds;
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
}
/** Returns all IDNs in which the {@code label} is valid. */
public ImmutableSet<IdnTableEnum> getAllValidIdns(String label) {
ImmutableSet<IdnTableEnum> getAllValidIdns(String label) {
return idnToTlds.keySet().stream()
.filter(idnTable -> idnTable.getTable().isValidLabel(label))
.collect(toImmutableSet());
@@ -75,8 +84,13 @@ public class IdnChecker {
*
* @param idnTables String names of {@link IdnTableEnum} values
*/
public ImmutableSet<Tld> getForbiddingTlds(ImmutableSet<String> idnTables) {
return Sets.difference(allTlds, getSupportingTlds(idnTables)).immutableCopy();
public SetView<Tld> getForbiddingTlds(ImmutableSet<String> idnTables) {
return Sets.difference(allTlds, getSupportingTlds(idnTables));
}
private static boolean isEnrolledWithBsa(Tld tld, DateTime now) {
DateTime enrollTime = tld.getBsaEnrollStartTime();
return enrollTime != null && enrollTime.isBefore(now);
}
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(DateTime now) {

View File

@@ -14,27 +14,32 @@
package google.registry.bsa;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.lock.LockHandler;
import java.util.concurrent.Callable;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import javax.inject.Inject;
import org.joda.time.Duration;
/** Helper for guarding all BSA related work with a common lock. */
public class BsaLock {
@Action(
service = Service.BSA,
path = PlaceholderAction.PATH,
method = Action.Method.GET,
auth = Auth.AUTH_API_ADMIN)
public class PlaceholderAction implements Runnable {
private final Response response;
private static final String LOCK_NAME = "all-bsa-jobs";
private final LockHandler lockHandler;
private final Duration leaseExpiry;
static final String PATH = "/_dr/task/bsaDownload";
@Inject
BsaLock(LockHandler lockHandler, @Config("bsaLockLeaseExpiry") Duration leaseExpiry) {
this.lockHandler = lockHandler;
this.leaseExpiry = leaseExpiry;
public PlaceholderAction(Response response) {
this.response = response;
}
boolean executeWithLock(Callable<Void> callable) {
return lockHandler.executeWithLocks(callable, null, leaseExpiry, LOCK_NAME);
@Override
public void run() {
response.setStatus(SC_OK);
response.setPayload("Hello World");
}
}

View File

@@ -1,30 +0,0 @@
// Copyright 2023 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.bsa;
public enum RefreshStage {
/**
* Checks for stale unblockable domains. The output is a stream of {@link
* google.registry.bsa.api.UnblockableDomainChange} objects that describe the stale domains.
*/
CHECK_FOR_CHANGES,
/** Fixes the stale domains in the database. */
APPLY_CHANGES,
/** Reports the unblockable domains to be removed to BSA. */
UPLOAD_REMOVALS,
/** Reports the newly found unblockable domains to BSA. */
UPLOAD_ADDITIONS,
DONE;
}

View File

@@ -1,78 +0,0 @@
// Copyright 2023 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.bsa;
import static com.google.common.base.Verify.verify;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.bsa.BsaStringUtils.DOMAIN_JOINER;
import static google.registry.flows.domain.DomainFlowUtils.isReserved;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.label.ReservedList.loadReservedLists;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldState;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.model.tld.label.ReservedList;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.joda.time.DateTime;
/**
* Utility for looking up reserved domain names.
*
* <p>This utility is only concerned with reserved domains that can be created (with appropriate
* tokens).
*/
public final class ReservedDomainsUtils {
private ReservedDomainsUtils() {}
public static Stream<String> getAllReservedNames(DateTime now) {
return Tlds.getTldEntitiesOfType(TldType.REAL).stream()
.filter(tld -> Tld.isEnrolledWithBsa(tld, now))
.map(tld -> getAllReservedDomainsInTld(tld, now))
.flatMap(ImmutableSet::stream);
}
/** Returns all reserved domains in a given {@code tld} as of {@code now}. */
static ImmutableSet<String> getAllReservedDomainsInTld(Tld tld, DateTime now) {
return loadReservedLists(tld.getReservedListNames()).stream()
.map(ReservedList::getReservedListEntries)
.map(Map::keySet)
.flatMap(Set::stream)
.map(label -> DOMAIN_JOINER.join(label, tld.getTldStr()))
.filter(domain -> isReservedDomain(domain, now))
.collect(toImmutableSet());
}
/**
* Returns true if {@code domain} is a reserved name that can be registered right now (e.g.,
* during sunrise or with allocation token), therefore unblockable.
*/
public static boolean isReservedDomain(String domain, DateTime now) {
Optional<InternetDomainName> tldStr = findTldForName(InternetDomainName.from(domain));
verify(tldStr.isPresent(), "Tld for domain [%s] unexpectedly missing.", domain);
Tld tld = Tld.get(tldStr.get().toString());
return isReserved(
InternetDomainName.from(domain),
Objects.equals(tld.getTldState(now), TldState.START_DATE_SUNRISE));
}
}

View File

@@ -1,283 +0,0 @@
// Copyright 2024 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.bsa;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Iterables.getLast;
import static google.registry.model.tld.Tld.isEnrolledWithBsa;
import static google.registry.model.tld.Tlds.getTldEntitiesOfType;
import static google.registry.model.tld.label.ReservedList.loadReservedLists;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static java.nio.charset.StandardCharsets.US_ASCII;
import com.google.api.client.http.HttpStatusCodes;
import com.google.cloud.storage.BlobId;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import google.registry.bsa.api.BsaCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.label.ReservedList;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Optional;
import java.util.zip.GZIPOutputStream;
import javax.inject.Inject;
import javax.persistence.TypedQuery;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.joda.time.DateTime;
/**
* Daily action that uploads unavailable domain names on applicable TLDs to BSA.
*
* <p>The upload is a single zipped text file containing combined details for all BSA-enrolled TLDs.
* The text is a newline-delimited list of punycoded fully qualified domain names, and contains all
* domains on each TLD that are registered and/or reserved.
*
* <p>The file is also uploaded to GCS to preserve it as a record for ourselves.
*/
@Action(
service = Service.BSA,
path = "/_dr/task/uploadBsaUnavailableNames",
method = {GET, POST},
auth = Auth.AUTH_API_ADMIN)
public class UploadBsaUnavailableDomainsAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final int BATCH_SIZE = 40000;
Clock clock;
BsaCredential bsaCredential;
GcsUtils gcsUtils;
String gcsBucket;
String apiUrl;
BsaEmailSender emailSender;
google.registry.request.Response response;
@Inject
public UploadBsaUnavailableDomainsAction(
Clock clock,
BsaCredential bsaCredential,
GcsUtils gcsUtils,
BsaEmailSender emailSender,
@Config("bsaUnavailableDomainsGcsBucket") String gcsBucket,
@Config("bsaUploadUnavailableDomainsUrl") String apiUrl,
google.registry.request.Response response) {
this.clock = clock;
this.bsaCredential = bsaCredential;
this.gcsUtils = gcsUtils;
this.gcsBucket = gcsBucket;
this.apiUrl = apiUrl;
this.emailSender = emailSender;
this.response = response;
}
@Override
public void run() {
// TODO(mcilwain): Implement a date Cursor, have the cronjob run frequently, and short-circuit
// the run if the daily upload is already completed.
DateTime runTime = clock.nowUtc();
String unavailableDomains = Joiner.on("\n").join(getUnavailableDomains(runTime));
if (unavailableDomains.isEmpty()) {
logger.atWarning().log("No unavailable domains found; terminating.");
emailSender.sendNotification(
"BSA daily upload found no domains to upload", "This is unexpected. Please investigate.");
} else {
boolean isGcsSuccess = uploadToGcs(unavailableDomains, runTime);
boolean isBsaSuccess = uploadToBsa(unavailableDomains, runTime);
if (isBsaSuccess && isGcsSuccess) {
emailSender.sendNotification("BSA daily upload completed successfully", "");
} else {
emailSender.sendNotification(
"BSA daily upload completed with errors", "Please see logs for details.");
}
}
}
/** Uploads the unavailable domains list to GCS in the unavailable domains bucket. */
boolean uploadToGcs(String unavailableDomains, DateTime runTime) {
logger.atInfo().log("Uploading unavailable names file to GCS in bucket %s", gcsBucket);
BlobId blobId = BlobId.of(gcsBucket, createFilename(runTime));
try (OutputStream gcsOutput = gcsUtils.openOutputStream(blobId);
Writer osWriter = new OutputStreamWriter(gcsOutput, US_ASCII)) {
osWriter.write(unavailableDomains);
return true;
} catch (Exception e) {
logger.atSevere().withCause(e).log(
"Error writing BSA unavailable domains to GCS; skipping to BSA upload ...");
return false;
}
}
boolean uploadToBsa(String unavailableDomains, DateTime runTime) {
try {
byte[] gzippedContents = gzipUnavailableDomains(unavailableDomains);
String sha512Hash = ByteSource.wrap(gzippedContents).hash(Hashing.sha512()).toString();
String filename = createFilename(runTime);
OkHttpClient client = new OkHttpClient().newBuilder().build();
RequestBody body =
new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"zone",
null,
RequestBody.create(
String.format("{\"checkSum\": \"%s\"}", sha512Hash).getBytes(US_ASCII),
MediaType.parse("application/json")))
.addFormDataPart(
"file",
String.format("%s.gz", filename),
RequestBody.create(gzippedContents, MediaType.parse("application/octet-stream")))
.build();
Request request =
new Request.Builder()
.url(apiUrl)
.method("POST", body)
.addHeader("Authorization", "Bearer " + bsaCredential.getAuthToken())
.build();
logger.atInfo().log(
"Uploading unavailable domains list %s to %s with hash %s", filename, apiUrl, sha512Hash);
try (Response uploadResponse = client.newCall(request).execute()) {
logger.atInfo().log(
"Received response with code %s from server: %s",
uploadResponse.code(),
uploadResponse.body() == null ? "(none)" : uploadResponse.body().string());
}
return true;
} catch (IOException e) {
logger.atSevere().withCause(e).log("Error while attempting to upload to BSA, aborting.");
response.setStatus(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
response.setPayload("Error while attempting to upload to BSA: " + e.getMessage());
return false;
}
}
private byte[] gzipUnavailableDomains(String unavailableDomains) throws IOException {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
gzipOutputStream.write(unavailableDomains.getBytes(US_ASCII));
}
return byteArrayOutputStream.toByteArray();
}
}
private static String createFilename(DateTime runTime) {
return String.format("unavailable_domains_%s.txt", runTime.toString());
}
private ImmutableSortedSet<String> getUnavailableDomains(DateTime runTime) {
// Get list of TLDs to process.
ImmutableSet<Tld> bsaEnabledTlds =
getTldEntitiesOfType(TldType.REAL).stream()
.filter(tld -> isEnrolledWithBsa(tld, runTime))
.collect(toImmutableSet());
logger.atInfo().log(
"Getting unavailable domains in TLDs: %s ...",
bsaEnabledTlds.stream().map(Tld::getTldStr).collect(toImmutableSet()));
ImmutableSortedSet.Builder<String> unavailableDomains =
new ImmutableSortedSet.Builder<>(Ordering.natural());
// Add domains on reserved lists to unavailable names list.
replicaTm()
.transact(
() -> {
for (Tld tld : bsaEnabledTlds) {
for (ReservedList reservedList : loadReservedLists(tld.getReservedListNames())) {
unavailableDomains.addAll(
reservedList.getReservedListEntries().keySet().stream()
.map(label -> toDomain(label, tld))
.collect(toImmutableSet()));
}
}
});
// Add existing domains to unavailable names list, in batches so as to not time out on replica.
ImmutableSet<String> tldNames =
bsaEnabledTlds.stream().map(Tld::getTldStr).collect(toImmutableSet());
ImmutableList<String> domainsBatch;
Optional<String> lastDomain = Optional.empty();
do {
final Optional<String> lastDomainCopy = lastDomain;
domainsBatch =
replicaTm()
.transact(
() -> {
String sql =
String.format(
"SELECT domainName FROM Domain "
+ "WHERE tld IN :tlds "
+ "AND deletionTime > :now "
+ "%s ORDER BY domainName ASC",
lastDomainCopy.isPresent()
? "AND domainName > :lastInPreviousBatch"
: "");
TypedQuery<String> query =
replicaTm()
.query(sql, String.class)
.setParameter("tlds", tldNames)
.setParameter("now", runTime);
lastDomainCopy.ifPresent(l -> query.setParameter("lastInPreviousBatch", l));
return query
.setMaxResults(BATCH_SIZE)
.getResultStream()
.collect(toImmutableList());
});
unavailableDomains.addAll(domainsBatch);
lastDomain = Optional.ofNullable(domainsBatch.isEmpty() ? null : getLast(domainsBatch));
} while (domainsBatch.size() == BATCH_SIZE);
ImmutableSortedSet<String> result = unavailableDomains.build();
logger.atInfo().log("Found %d total unavailable domains.", result.size());
return result;
}
private static String toDomain(String domainLabel, Tld tld) {
return String.format("%s.%s", domainLabel, tld.getTldStr());
}
}

View File

@@ -1,64 +0,0 @@
// Copyright 2023 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.bsa.api;
import com.google.auto.value.AutoValue;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import java.util.List;
/**
* A BSA label to block. New domains with matching second-level domain (SLD) will be denied
* registration in TLDs enrolled with BSA.
*/
@AutoValue
public abstract class BlockLabel {
static final Joiner JOINER = Joiner.on(',');
static final Splitter SPLITTER = Splitter.on(',').trimResults();
public abstract String label();
public abstract LabelType labelType();
public abstract ImmutableSet<String> idnTables();
public String serialize() {
return JOINER.join(label(), labelType().name(), idnTables().stream().sorted().toArray());
}
public static BlockLabel deserialize(String text) {
List<String> items = SPLITTER.splitToList(text);
try {
return of(
items.get(0),
LabelType.valueOf(items.get(1)),
ImmutableSet.copyOf(items.subList(2, items.size())));
} catch (NumberFormatException ne) {
throw new IllegalArgumentException(text);
}
}
public static BlockLabel of(String label, LabelType type, ImmutableSet<String> idnTables) {
return new AutoValue_BlockLabel(label, type, idnTables);
}
public enum LabelType {
CREATE,
NEW_ORDER_ASSOCIATION,
DELETE;
}
}

View File

@@ -1,57 +0,0 @@
// Copyright 2023 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.bsa.api;
import com.google.auto.value.AutoValue;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.util.List;
/**
* A BSA order, which are needed when communicating with the BSA API while processing downloaded
* block lists.
*/
@AutoValue
public abstract class BlockOrder {
public abstract long orderId();
public abstract OrderType orderType();
static final Joiner JOINER = Joiner.on(',');
static final Splitter SPLITTER = Splitter.on(',');
public String serialize() {
return JOINER.join(orderId(), orderType().name());
}
public static BlockOrder deserialize(String text) {
List<String> items = SPLITTER.splitToList(text);
try {
return of(Long.valueOf(items.get(0)), OrderType.valueOf(items.get(1)));
} catch (NumberFormatException ne) {
throw new IllegalArgumentException(text);
}
}
public static BlockOrder of(long orderId, OrderType orderType) {
return new AutoValue_BlockOrder(orderId, orderType);
}
public enum OrderType {
CREATE,
DELETE;
}
}

View File

@@ -1,160 +0,0 @@
// Copyright 2023 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.bsa.api;
import static google.registry.request.UrlConnectionUtils.getResponseBytes;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.api.client.http.HttpMethods;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.FluentLogger;
import com.google.gson.Gson;
import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.api.Keyring;
import google.registry.request.UrlConnectionService;
import google.registry.request.UrlConnectionUtils;
import google.registry.util.Clock;
import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import javax.net.ssl.HttpsURLConnection;
import org.joda.time.Duration;
import org.joda.time.Instant;
/**
* A credential for accessing the BSA API.
*
* <p>Fetches on-demand an auth token from BSA's auth http endpoint and caches it for repeated use
* until the token expires (expiry set by BSA and recorded in the configuration file). An expired
* token is refreshed only when requested. Token refreshing is blocking but thread-safe.
*
* <p>The token-fetching request authenticates itself with an API key, which is stored in the Secret
* Manager.
*/
@ThreadSafe
public class BsaCredential {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
/** Content type of the auth http request. */
private static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
/** Template of the auth http request's payload. User must provide an API key. */
private static final String AUTH_REQ_BODY_TEMPLATE = "apiKey=%s&space=BSA";
/** The variable name for the auth token in the returned json response. */
public static final String ID_TOKEN = "id_token";
private final UrlConnectionService urlConnectionService;
private final String authUrl;
private final Duration authTokenExpiry;
private final Keyring keyring;
private final Clock clock;
@Nullable private String authToken;
private Instant lastRefreshTime;
@Inject
BsaCredential(
UrlConnectionService urlConnectionService,
@Config("bsaAuthUrl") String authUrl,
@Config("bsaAuthTokenExpiry") Duration authTokenExpiry,
Keyring keyring,
Clock clock) {
this.urlConnectionService = urlConnectionService;
this.authUrl = authUrl;
this.authTokenExpiry = authTokenExpiry;
this.keyring = keyring;
this.clock = clock;
}
/**
* Returns the auth token for accessing the BSA API.
*
* <p>This method refreshes the token if it is expired, and is thread-safe..
*/
public String getAuthToken() {
try {
ensureAuthTokenValid();
} catch (IOException e) {
throw new BsaException(e, /* retriable= */ true);
} catch (GeneralSecurityException e) {
throw new BsaException(e, /* retriable= */ false);
}
return this.authToken;
}
private void ensureAuthTokenValid() throws IOException, GeneralSecurityException {
Instant now = Instant.ofEpochMilli(clock.nowUtc().getMillis());
if (authToken != null && lastRefreshTime.plus(authTokenExpiry).isAfter(now)) {
logger.atInfo().log("AuthToken still valid, reusing.");
return;
}
synchronized (this) {
authToken = fetchNewAuthToken();
lastRefreshTime = now;
logger.atInfo().log("AuthToken refreshed at %s.", now);
}
}
@VisibleForTesting
String fetchNewAuthToken() throws IOException, GeneralSecurityException {
String payload = String.format(AUTH_REQ_BODY_TEMPLATE, keyring.getBsaApiKey());
URL url = new URL(authUrl);
logger.atInfo().log("Fetching auth token from %s", url);
HttpsURLConnection connection = null;
try {
connection = (HttpsURLConnection) urlConnectionService.createConnection(url);
connection.setRequestMethod(HttpMethods.POST);
UrlConnectionUtils.setPayload(connection, payload.getBytes(UTF_8), CONTENT_TYPE);
int code = connection.getResponseCode();
if (code != SC_OK) {
String errorDetails;
try {
errorDetails = new String(getResponseBytes(connection), UTF_8);
} catch (Exception e) {
errorDetails = "Failed to retrieve error message: " + e.getMessage();
}
throw new BsaException(
String.format(
"Status code: [%s], error: [%s], details: [%s]",
code, connection.getResponseMessage(), errorDetails),
/* retriable= */ true);
}
// TODO: catch json syntax exception
@SuppressWarnings("unchecked")
String idToken =
new Gson()
.fromJson(new String(getResponseBytes(connection), UTF_8), Map.class)
.getOrDefault(ID_TOKEN, "")
.toString();
if (idToken.isEmpty()) {
throw new BsaException("Response missing ID token", /* retriable= */ false);
}
return idToken;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More