mirror of
https://github.com/google/nomulus.git
synced 2025-08-01 23:42:12 +02:00
Build Nomulus with Java 17 (#2255)
This PR makes it possible to build the Nomulus code base using Java 17. Building with Java 11 continue to be possible and the resulting bytecodes are still at Java 8 level. Also upgraded Gradle to 8.5. There are several necessary changes to make this happen: 1. Some Gradle plugins need to be upgraded to support Java 17, notably errorprone. As a result, a lot more "errors" were caught and corrected. 2. All test code are now built and run at Java 8 level. Previously it was left undefined (which defaults to the version of the compiler) and had led to situations where we inadvertently called Java 8+ features in production that are not caught by tests. The change also made the java8compatibility subproject obsolete, which is therefore removed. 3. Removed the docs subproject. Its main use is to generate flows.md, but it relies heavily on Java internal APIs that have changed significant with each version. Upgrading to Java 11 required extensive refactoring of the code there, and Java 17 again removed many APIs that were used. I don't think it is worth the maintenance effort just to have a tool to generate flows.md which no one actually reads. 4. Capped a few GCP dependencies because the latest version depends on grpc-java >= 1.59.0, which includes a runtime incompatibility (https://github.com/grpc/grpc-java/releases/tag/v1.59.0).
This commit is contained in:
parent
e79c63142a
commit
b5d2b56426
134 changed files with 750 additions and 3731 deletions
|
@ -1,69 +0,0 @@
|
|||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
implementation deps['com.beust:jcommander']
|
||||
implementation deps['com.google.appengine:appengine-api-1.0-sdk']
|
||||
implementation deps['com.google.code.findbugs:jsr305']
|
||||
implementation deps['com.google.flogger:flogger']
|
||||
implementation deps['com.google.guava:guava']
|
||||
implementation deps['com.google.re2j:re2j']
|
||||
implementation project(':core')
|
||||
implementation project(':util')
|
||||
|
||||
testImplementation deps['com.google.truth:truth']
|
||||
testImplementation deps['com.thoughtworks.qdox:qdox']
|
||||
testImplementation deps['junit:junit']
|
||||
testImplementation deps['org.junit.jupiter:junit-jupiter-api']
|
||||
testImplementation deps['org.junit.jupiter:junit-jupiter-engine']
|
||||
testImplementation deps['org.junit.platform:junit-platform-runner']
|
||||
testImplementation deps['org.junit.platform:junit-platform-suite-api']
|
||||
testImplementation deps['org.testcontainers:junit-jupiter']
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
task flowDocsTool(type: JavaExec) {
|
||||
systemProperty 'test.projectRoot', rootProject.projectRootDir
|
||||
jvmArgs = ['--add-exports', 'jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED']
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
main = 'google.registry.documentation.FlowDocumentationTool'
|
||||
|
||||
def arguments = []
|
||||
if (rootProject.flowDocsFile) {
|
||||
arguments << "--output_file=${rootProject.flowDocsFile}"
|
||||
} else {
|
||||
arguments << "--output_file=${rootProject.projectRootDir}/docs/flows.md"
|
||||
}
|
||||
args arguments
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.compilerArgs = ["--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED"]
|
||||
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
jvmArgs = ['--add-exports',
|
||||
'jdk.javadoc/jdk.javadoc.internal.tool=ALL-UNNAMED']
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
# 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.
|
||||
empty=classpath
|
1072
docs/flows.md
1072
docs/flows.md
File diff suppressed because it is too large
Load diff
|
@ -1,385 +0,0 @@
|
|||
# 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.
|
||||
antlr:antlr:2.7.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
aopalliance:aopalliance:1.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
args4j:args4j:2.33=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.101tec:zkclient:0.10=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.beust:jcommander:1.60=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.10.3=testCompileClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson:jackson-bom:2.15.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.5.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.ben-manes.caffeine:caffeine:2.7.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.github.ben-manes.caffeine:caffeine:2.9.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-api:3.3.4=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport-zerodep:3.3.4=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.docker-java:docker-java-transport:3.3.4=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jffi:1.3.12=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-a64asm:1.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-constants:0.10.4=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-enxio:0.32.16=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-ffi:2.2.15=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-posix:3.1.18=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-unixsocket:0.38.21=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.jnr:jnr-x86asm:1.0.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.android:annotations:4.1.1.4=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-appengine:1.35.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-jackson2:2.0.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-java6:1.35.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client-servlet:1.35.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api-client:google-api-client:1.35.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:gapic-google-cloud-storage-v2:2.22.6-alpha=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:2.47.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.171.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.171.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.30.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.107.13=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.12.19=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-cloud-storage-v2:2.23.0-alpha=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:grpc-google-common-protos:2.29.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:2.47.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.171.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.171.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.30.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.30.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-datastore-v1:0.108.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-firestore-v1:3.15.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.32.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.107.13=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.12.19=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.23.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta1:2.23.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-spanner-v1:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-storage-v2:2.23.0-alpha=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2:2.23.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.122.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.122.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-common-protos:2.29.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api.grpc:proto-google-iam-v1:1.24.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api:api-common:2.21.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-grpc:2.38.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api:gax-httpjson:2.38.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.api:gax:2.38.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-admin-directory:directory_v1-rev118-1.25.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-appengine:v1-rev20231107-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-bigquery:v2-rev20230812-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20230806-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dataflow:v1b3-rev20220920-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-dns:v2beta1-rev99-1.25.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-drive:v2-rev393-1.25.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-gmail:v1-rev20220404-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-groupssettings:v1-rev20210624-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-healthcare:v1-rev20231101-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-monitoring:v3-rev20231215-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sheets:v4-rev20230815-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-sqladmin:v1beta4-rev20231208-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.apis:google-api-services-storage:v1-rev20231202-2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-api-1.0-sdk:1.9.86=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.appengine:appengine-testing:1.9.86=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-credentials:1.20.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auth:google-auth-library-oauth2-http:1.20.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auto.service:auto-service-annotations:1.1.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value-annotations:1.10.4=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.auto.value:auto-value:1.10.4=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.auto:auto-common:0.10=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.cloud.bigdataoss:gcsio:2.2.16=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigdataoss:util:2.2.16=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.datastore:datastore-v1-proto-client:2.17.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:jdbc-socket-factory-core:1.15.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud.sql:postgres-socket-factory:1.15.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigquerystorage:2.47.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable-stats:2.30.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-bigtable:2.30.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-grpc:2.28.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core-http:2.21.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-core:2.28.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-firestore:3.15.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-monitoring:3.32.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsub:1.125.13=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-pubsublite:1.12.19=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-secretmanager:2.23.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-spanner:6.55.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-storage:2.22.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:google-cloud-tasks:2.32.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:grpc-gcp:1.5.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.15.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.code.findbugs:jFormatString:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.code.gson:gson:2.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.common.html.types:types:1.0.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.dagger:dagger:2.50=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.errorprone:error_prone_annotation:2.3.4=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.errorprone:error_prone_annotations:2.23.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
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.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.escapevelocity:escapevelocity:0.9.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.flatbuffers:flatbuffers-java:1.12.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.flogger:flogger-system-backend:0.8=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.flogger:google-extensions:0.8=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
|
||||
com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:guava:27.0.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.guava:guava:31.0.1-jre=checkstyle
|
||||
com.google.guava:guava:33.0.0-jre=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.gwt:gwt-user:2.10.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-apache-v2:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-appengine:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-gson:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-jackson2:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client-protobuf:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.http-client:google-http-client:1.43.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.inject.extensions:guice-multibindings:4.1.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.inject:guice:4.1.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.j2objc:j2objc-annotations:1.3=checkstyle
|
||||
com.google.j2objc:j2objc-annotations:2.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.jsinterop:jsinterop-annotations:2.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:metrics:1.0.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.monitoring-client:stackdriver:1.0.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-appengine:1.34.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-java6:1.34.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-jetty:1.34.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client-servlet:1.34.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.oauth-client:google-oauth-client:1.34.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java-util:3.25.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.25.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.protobuf:protobuf-java:3.4.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.google.template:soy:2021-02-01=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.google.truth:truth:1.2.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.googlecode.java-diff-utils:diffutils:1.3.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
com.googlecode.json-simple:json-simple:1.1.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.ibm.icu:icu4j:74.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.jcraft:jsch:0.1.55=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.lmax:disruptor:3.4.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.puppycrawl.tools:checkstyle:9.3=checkstyle
|
||||
com.squareup.okhttp3:okhttp:4.12.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.squareup.okio:okio-jvm:3.6.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.squareup.okio:okio:3.6.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.sun.istack:istack-commons-runtime:3.0.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.sun.xml.fastinfoset:FastInfoset:1.2.15=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.paranamer:paranamer:2.7=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
com.thoughtworks.qdox:qdox:1.12.1=testCompileClasspath,testRuntimeClasspath
|
||||
com.zaxxer:HikariCP:3.4.5=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
commons-beanutils:commons-beanutils:1.9.4=checkstyle
|
||||
commons-codec:commons-codec:1.16.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
commons-collections:commons-collections:3.2.2=checkstyle
|
||||
commons-logging:commons-logging:1.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
dnsjava:dnsjava:3.5.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
info.picocli:picocli:4.6.2=checkstyle
|
||||
io.confluent:common-config:5.3.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.confluent:common-utils:5.3.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.confluent:kafka-avro-serializer:5.3.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.confluent:kafka-schema-registry-client:5.3.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.github.classgraph:classgraph:4.8.162=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.github.java-diff-utils:java-diff-utils:4.12=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-alts:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-api:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-auth:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-census:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-context:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-core:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-googleapis:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-grpclb:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-inprocess:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty-shaded:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-netty:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf-lite:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-protobuf:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-rls:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-services:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-stub:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-util:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.grpc:grpc-xds:1.59.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec-socks:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler-proxy:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-tcnative-classes:2.0.52.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.97.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-api:0.31.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-metrics:0.31.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-grpc-util:0.31.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-http-util:0.31.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-contrib-resource-util:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-exporter-metrics-util:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-exporter-stats-stackdriver:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl-core:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-impl:0.31.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.opencensus:opencensus-proto:0.2.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
io.perfmark:perfmark-api:0.26.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.activation:activation:1.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.activation:javax.activation-api:1.2.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.annotation:javax.annotation-api:1.3.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.annotation:jsr250-api:1.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.inject:javax.inject:1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
javax.jdo:jdo2-api:2.3-20090302111651=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.mail:mail:1.5.0-b01=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.persistence:javax.persistence-api:2.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.servlet:servlet-api:2.5=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.validation:validation-api:1.0.0.GA=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
javax.xml.bind:jaxb-api:2.3.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
jline:jline:1.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
joda-time:joda-time:2.10.14=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.12.18=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
net.java.dev.jna:jna:5.13.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
net.sf.saxon:Saxon-HE:10.6=checkstyle
|
||||
org.antlr:antlr4-runtime:4.9.3=checkstyle
|
||||
org.apache.arrow:arrow-format:5.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-memory-core:5.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.arrow:arrow-vector:5.0.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.avro:avro:1.8.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-fn-execution:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-job-management:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-model-pipeline:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-construction-java:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-core-java:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-runners-java-fn-execution:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-core:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-expansion-service:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-arrow:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-avro:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-extensions-protobuf:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-fn-execution:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-harness:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-io-kafka:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-sdks-java-transform-service-launcher:2.53.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-grpc-1_54_0:0.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-compress:1.24.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-csv:1.10.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.14.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.14=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.16=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
|
||||
org.bouncycastle:bcpg-jdk15on:1.67=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcpkix-jdk15on:1.67=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.bouncycastle:bcprov-jdk15on:1.67=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.3=compileClasspath,testCompileClasspath
|
||||
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.checkerframework:checker-qual:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.checkerframework:checker-qual:3.12.0=checkstyle
|
||||
org.checkerframework:checker-qual:3.41.0=compileClasspath
|
||||
org.checkerframework:checker-qual:3.42.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.checkerframework:dataflow:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.checkerframework:javacutil:3.0.0=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.codehaus.jackson:jackson-core-asl:1.9.13=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.codehaus.jackson:jackson-mapper-asl:1.9.13=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,errorprone,testAnnotationProcessor
|
||||
org.codehaus.mojo:animal-sniffer-annotations:1.23=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.conscrypt:conscrypt-openjdk-uber:2.5.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-servlet:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util-ajax:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:9.4.49.v20220914=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.flywaydb:flyway-core:9.22.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:jaxb-runtime:2.3.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.glassfish.jaxb:txw2:2.3.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.gwtproject:gwt-user:2.10.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.hamcrest:hamcrest:2.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.hibernate.common:hibernate-commons-annotations:5.1.2.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-core:5.6.15.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.hibernate:hibernate-hikaricp:5.6.15.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
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=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jboss:jandex:2.4.2.Final=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.9.10=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jetbrains:annotations:17.0.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.joda:joda-money:1.0.4=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.json:json:20231013=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.jsoup:jsoup:1.17.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-runner:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-api:1.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-suite-commons:1.10.1=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.10.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.jvnet.staxex:stax-ex:1.8=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-analysis:9.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-commons:9.5=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.5=jacocoAnt
|
||||
org.ow2.asm:asm-tree:9.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm-util:9.6=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.ow2.asm:asm:9.5=jacocoAnt
|
||||
org.ow2.asm:asm:9.6=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
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.postgresql:postgresql:42.7.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.reflections:reflections:0.10.2=checkstyle
|
||||
org.rnorth.duct-tape:duct-tape:1.0.8=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:1.7.36=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.springframework:spring-core:5.3.27=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-expression:5.3.27=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-jcl:5.3.27=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:database-commons:1.19.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:jdbc:1.19.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:junit-jupiter:1.19.3=testCompileClasspath,testRuntimeClasspath
|
||||
org.testcontainers:postgresql:1.19.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.testcontainers:testcontainers:1.19.3=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.threeten:threetenbp:1.6.8=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.tukaani:xz:1.5=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.w3c.css:sac:1.3=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.xerial.snappy:snappy-java:1.1.10.4=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:2.0=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-api:16.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-diagram:16.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-tools:16.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler-utility:16.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
us.fatehi:schemacrawler:16.10.1=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
xerces:xmlParserAPIs:2.6.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
xpp3:xpp3:1.1.4c=deploy_jar,runtimeClasspath,testRuntimeClasspath
|
||||
empty=errorproneJavac
|
|
@ -1,81 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static java.util.Comparator.comparing;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.documentation.FlowDocumentation.ErrorCase;
|
||||
import java.util.stream.Stream;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import jdk.javadoc.doclet.DocletEnvironment;
|
||||
|
||||
/**
|
||||
* Main entry point class for documentation generation. An instance of this class reads data via the
|
||||
* javadoc system upon creation and stores it for answering future queries for documentation
|
||||
* information.
|
||||
*/
|
||||
public final class DocumentationGenerator {
|
||||
|
||||
private final DocletEnvironment sourceRoot;
|
||||
|
||||
/** Returns a new DocumentationGenerator object with parsed information from javadoc. */
|
||||
public DocumentationGenerator() throws Exception {
|
||||
sourceRoot = JavadocWrapper.getDocletEnv();
|
||||
}
|
||||
|
||||
/** Returns generated Markdown output for the flows. Convenience method for clients. */
|
||||
public String generateMarkdown() {
|
||||
return MarkdownDocumentationFormatter.generateMarkdownOutput(getFlowDocs());
|
||||
}
|
||||
|
||||
/** Returns a list of flow documentation objects derived from this generator's data. */
|
||||
public ImmutableList<FlowDocumentation> getFlowDocs() {
|
||||
// Relevant flows are leaf flows: precisely the concrete subclasses of Flow.
|
||||
return getConcreteSubclassesStream(FlowDocumentation.BASE_FLOW_CLASS_NAME)
|
||||
.sorted(comparing(element -> element.getSimpleName().toString()))
|
||||
.map(typeElement -> new FlowDocumentation(typeElement, sourceRoot))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
/** Returns a list of all possible error cases that might occur. */
|
||||
public ImmutableList<ErrorCase> getAllErrors() {
|
||||
// Relevant error cases are precisely the concrete subclasses of EppException.
|
||||
return getConcreteSubclassesStream(FlowDocumentation.EXCEPTION_CLASS_NAME)
|
||||
.map(
|
||||
typeElement ->
|
||||
new ErrorCase(
|
||||
typeElement,
|
||||
sourceRoot.getDocTrees().getDocCommentTree(typeElement),
|
||||
sourceRoot.getTypeUtils()))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
/** Helper to return all concrete subclasses of a given named class. */
|
||||
private Stream<TypeElement> getConcreteSubclassesStream(String baseClassName) {
|
||||
final TypeElement baseFlowTypeElement =
|
||||
sourceRoot.getElementUtils().getTypeElement(baseClassName);
|
||||
return ElementFilter.typesIn(sourceRoot.getIncludedElements()).stream()
|
||||
.filter(
|
||||
typeElement ->
|
||||
sourceRoot
|
||||
.getTypeUtils()
|
||||
.isSubtype(typeElement.asType(), baseFlowTypeElement.asType())
|
||||
&& !typeElement.getModifiers().contains(Modifier.ABSTRACT));
|
||||
}
|
||||
}
|
|
@ -1,370 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.DocTree.Kind;
|
||||
import com.sun.source.doctree.LinkTree;
|
||||
import com.sun.source.doctree.ReferenceTree;
|
||||
import com.sun.source.doctree.UnknownBlockTagTree;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.model.eppoutput.Result.Code;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.TreeMap;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import jdk.javadoc.doclet.DocletEnvironment;
|
||||
|
||||
/**
|
||||
* Class to represent documentation information for a single EPP flow.
|
||||
*
|
||||
* <p>The static method {@link DocumentationGenerator#getFlowDocs} returns a list of {@link
|
||||
* FlowDocumentation} instances corresponding to the leaf flows in the flows package, constructing
|
||||
* the instances from class information returned from the javadoc system. Each instance has methods
|
||||
* for retrieving relevant information about the flow, such as a description, error conditions, etc.
|
||||
*/
|
||||
public class FlowDocumentation {
|
||||
|
||||
/** Constants for names of various relevant packages and classes. */
|
||||
static final String FLOW_PACKAGE_NAME = "google.registry.flows";
|
||||
|
||||
static final String BASE_FLOW_CLASS_NAME = FLOW_PACKAGE_NAME + ".Flow";
|
||||
static final String EXCEPTION_CLASS_NAME = FLOW_PACKAGE_NAME + ".EppException";
|
||||
static final String CODE_ANNOTATION_NAME = EXCEPTION_CLASS_NAME + ".EppResultCode";
|
||||
|
||||
/** Root of the source doclet environment. */
|
||||
private final DocletEnvironment sourceRoot;
|
||||
|
||||
/** Type Element of the class. */
|
||||
private final TypeElement typeElement;
|
||||
|
||||
/** Doc tree for the flow. */
|
||||
private final DocCommentTree docTree;
|
||||
|
||||
/** Javadoc-tagged error conditions for this flow in list form. */
|
||||
private final List<ErrorCase> errors;
|
||||
|
||||
/** Javadoc-tagged error conditions for this flow, organized by underlying error code. */
|
||||
private final ListMultimap<Long, ErrorCase> errorsByCode;
|
||||
|
||||
/**
|
||||
* Creates a {@link FlowDocumentation} for this flow class using data from javadoc tags. Not
|
||||
* public because clients should get FlowDocumentation objects via the DocumentationGenerator
|
||||
* class.
|
||||
*/
|
||||
protected FlowDocumentation(TypeElement typeElement, DocletEnvironment sourceRoot) {
|
||||
this.sourceRoot = sourceRoot;
|
||||
this.typeElement = typeElement;
|
||||
this.docTree = sourceRoot.getDocTrees().getDocCommentTree(typeElement);
|
||||
errors = new ArrayList<>();
|
||||
// Store error codes in sorted order, and leave reasons in insert order.
|
||||
errorsByCode = Multimaps.newListMultimap(new TreeMap<>(), ArrayList::new);
|
||||
parseTags();
|
||||
}
|
||||
|
||||
/** Name of the class for this flow. */
|
||||
public String getName() {
|
||||
return typeElement.getSimpleName().toString();
|
||||
}
|
||||
|
||||
/** Fully qualified name of the class for this flow. */
|
||||
public String getQualifiedName() {
|
||||
return typeElement.getQualifiedName().toString();
|
||||
}
|
||||
|
||||
/** Name of the package in which this flow resides. */
|
||||
public String getPackageName() {
|
||||
return sourceRoot.getElementUtils().getPackageOf(typeElement).getQualifiedName().toString();
|
||||
}
|
||||
|
||||
/** Javadoc of the class. */
|
||||
public String getDocTree() {
|
||||
StringJoiner joiner = new StringJoiner("");
|
||||
docTree.getFullBody().forEach(dt -> joiner.add(dt.toString()));
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
public ImmutableList<ErrorCase> getErrors() {
|
||||
return ImmutableList.copyOf(errors);
|
||||
}
|
||||
|
||||
public ImmutableMultimap<Long, ErrorCase> getErrorsByCode() {
|
||||
return ImmutableMultimap.copyOf(errorsByCode);
|
||||
}
|
||||
|
||||
/** Iterates through javadoc tags on the underlying class and calls specific parsing methods. */
|
||||
private void parseTags() {
|
||||
for (DocTree tag : docTree.getBlockTags()) {
|
||||
if (tag.getKind() == DocTree.Kind.UNKNOWN_BLOCK_TAG) {
|
||||
UnknownBlockTagTree unknownBlockTagTree = (UnknownBlockTagTree) tag;
|
||||
// Everything else is not a relevant tag.
|
||||
if (unknownBlockTagTree.getTagName().equals("error")) {
|
||||
parseErrorTag(unknownBlockTagTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Exception to throw when an @error tag cannot be parsed correctly. */
|
||||
private static class BadErrorTagFormatException extends IllegalStateException {
|
||||
/** Makes a message to use as a prefix for the reason passed up to the superclass. */
|
||||
private static String makeMessage(
|
||||
String reason, TypeElement typeElement, UnknownBlockTagTree tagTree) {
|
||||
return String.format(
|
||||
"Bad @error tag format (%s) in class %s - %s",
|
||||
tagTree.toString(), typeElement.getQualifiedName(), reason);
|
||||
}
|
||||
|
||||
private BadErrorTagFormatException(
|
||||
String reason, TypeElement typeElement, UnknownBlockTagTree tagTree) {
|
||||
super(makeMessage(reason, typeElement, tagTree));
|
||||
}
|
||||
|
||||
private BadErrorTagFormatException(
|
||||
String reason, TypeElement typeElement, UnknownBlockTagTree tagTree, Exception cause) {
|
||||
super(makeMessage(reason, typeElement, tagTree), cause);
|
||||
}
|
||||
}
|
||||
|
||||
/** Parses a javadoc tag corresponding to an error case and updates the error mapping. */
|
||||
private void parseErrorTag(UnknownBlockTagTree tagTree) {
|
||||
// Parse the @error tag text to find the @link inline tag.
|
||||
LinkTree linkedTag;
|
||||
try {
|
||||
linkedTag =
|
||||
tagTree.getContent().stream()
|
||||
.filter(docTree -> docTree.getKind() == Kind.LINK)
|
||||
.map(LinkTree.class::cast)
|
||||
.collect(onlyElement());
|
||||
} catch (NoSuchElementException | IllegalArgumentException e) {
|
||||
throw new BadErrorTagFormatException(
|
||||
String.format(
|
||||
"expected one @link tag in tag text but found %s: %s",
|
||||
(e instanceof NoSuchElementException ? "none" : "multiple"), tagTree.toString()),
|
||||
typeElement,
|
||||
tagTree,
|
||||
e);
|
||||
}
|
||||
// Check to see if the @link tag references a valid class.
|
||||
ReferenceTree referenceTree = linkedTag.getReference();
|
||||
TypeElement referencedTypeElement = getReferencedElement(referenceTree);
|
||||
if (referencedTypeElement == null) {
|
||||
throw new BadErrorTagFormatException(
|
||||
"could not resolve class from @link tag text: " + linkedTag.toString(),
|
||||
typeElement,
|
||||
tagTree);
|
||||
}
|
||||
// Try to convert the referenced class into an ErrorCase; fail if it's not an EppException.
|
||||
ErrorCase error;
|
||||
try {
|
||||
DocCommentTree docCommentTree =
|
||||
sourceRoot.getDocTrees().getDocCommentTree(referencedTypeElement);
|
||||
error = new ErrorCase(referencedTypeElement, docCommentTree, sourceRoot.getTypeUtils());
|
||||
} catch (IllegalStateException | IllegalArgumentException e) {
|
||||
throw new BadErrorTagFormatException(
|
||||
"class referenced in @link is not a valid EppException: "
|
||||
+ referencedTypeElement.getQualifiedName(),
|
||||
typeElement,
|
||||
tagTree,
|
||||
e);
|
||||
}
|
||||
// Success; store this as a parsed error case.
|
||||
errors.add(error);
|
||||
errorsByCode.put(error.getCode(), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find the {@link TypeElement} of the class in the {@link ReferenceTree}.
|
||||
*
|
||||
* <p>Unfortunately the new Javadoc API doesn't expose the referenced class object directly, so we
|
||||
* have to find it by trying to find out its fully qualified class name and then loading it from
|
||||
* the {@link Elements}.
|
||||
*/
|
||||
private TypeElement getReferencedElement(ReferenceTree referenceTree) {
|
||||
String signature = referenceTree.getSignature();
|
||||
Elements elements = sourceRoot.getElementUtils();
|
||||
TypeElement referencedTypeElement = elements.getTypeElement(signature);
|
||||
// If the signature is already a qualified class name, we should find it directly. Otherwise
|
||||
// only the simple class name is used in the @error tag and we try to find its package name.
|
||||
if (referencedTypeElement == null) {
|
||||
// First try if the error class is in the same package as the flow class that we are
|
||||
// processing.
|
||||
referencedTypeElement =
|
||||
elements.getTypeElement(String.format("%s.%s", getPackageName(), signature));
|
||||
}
|
||||
if (referencedTypeElement == null) {
|
||||
// Then try if the error class is a nested class of the flow class that we are processing.
|
||||
referencedTypeElement =
|
||||
elements.getTypeElement(String.format("%s.%s", getQualifiedName(), signature));
|
||||
}
|
||||
if (referencedTypeElement == null) {
|
||||
// Lastly, the error class must have been imported. We read the flow class file, and try to
|
||||
// find the import statement that ends with the simple class name.
|
||||
String currentClassFilename =
|
||||
String.format(
|
||||
"%s/%s.java",
|
||||
JavadocWrapper.SOURCE_PATH, getQualifiedName().replaceAll("\\.", "\\/"));
|
||||
String unusedClassFileContent;
|
||||
try {
|
||||
unusedClassFileContent = Files.readString(Path.of(currentClassFilename), UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// To understand this regex: the import statement must start with a new line or a semicolon,
|
||||
// followed by any number of whitespaces, the word "import" (we don't consider static import),
|
||||
// any number of whitespaces, repeats of "\w*." (this is not exactly precise, but for all
|
||||
// well-named classes it should suffice), the signature, any number of whitespaces, and
|
||||
// finally an ending semicolon. "?:" is used to designate non-capturing groups as we are only
|
||||
// interested in capturing the fully qualified class name.
|
||||
Pattern pattern =
|
||||
Pattern.compile(String.format("(?:\\n|;)\\s*import\\s+((?:\\w*\\.)*%s)\\s*;", signature));
|
||||
Matcher matcher = pattern.matcher(unusedClassFileContent);
|
||||
if (matcher.find()) {
|
||||
referencedTypeElement = elements.getTypeElement(matcher.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
return referencedTypeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an error case for a flow, with a reason for the error and the EPP error code.
|
||||
*
|
||||
* <p>This class is an immutable wrapper for the name of an {@link EppException} subclass that
|
||||
* gets thrown to indicate an error condition. It overrides {@code equals()} and {@code
|
||||
* hashCode()} so that instances of this class can be used in collections in the normal fashion.
|
||||
*/
|
||||
public static class ErrorCase {
|
||||
|
||||
/** The non-qualified name of the exception class. */
|
||||
private final String name;
|
||||
|
||||
/** The fully-qualified name of the exception class. */
|
||||
private final String className;
|
||||
|
||||
/** The reason this error was thrown, normally documented on the low-level exception class. */
|
||||
private final String reason;
|
||||
|
||||
/** Utility class to convert {@link TypeMirror} to {@link TypeElement}. */
|
||||
private final Types types;
|
||||
|
||||
/** The EPP error code value corresponding to this error condition. */
|
||||
private final long errorCode;
|
||||
|
||||
/** Constructs an ErrorCase from the corresponding class for a low-level flow exception. */
|
||||
protected ErrorCase(TypeElement typeElement, DocCommentTree commentTree, Types types) {
|
||||
name = typeElement.getSimpleName().toString();
|
||||
className = typeElement.getQualifiedName().toString();
|
||||
// The javadoc comment on the class explains the reason for the error condition.
|
||||
reason = commentTree.getFullBody().toString();
|
||||
this.types = types;
|
||||
TypeElement highLevelExceptionTypeElement = getHighLevelExceptionFrom(typeElement);
|
||||
errorCode = extractErrorCode(highLevelExceptionTypeElement);
|
||||
checkArgument(
|
||||
!typeElement.getModifiers().contains(Modifier.ABSTRACT),
|
||||
"Cannot use an abstract subclass of EppException as an error case");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public long getCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/** Returns the direct subclass of EppException that this class is a subclass of (or is). */
|
||||
private TypeElement getHighLevelExceptionFrom(TypeElement typeElement) {
|
||||
// While we're not yet at the root, move up the class hierarchy looking for EppException.
|
||||
while (typeElement.getSuperclass() != null) {
|
||||
TypeElement superClassTypeElement =
|
||||
(TypeElement) types.asElement(typeElement.getSuperclass());
|
||||
if (superClassTypeElement.getQualifiedName().toString().equals(EXCEPTION_CLASS_NAME)) {
|
||||
return typeElement;
|
||||
}
|
||||
typeElement = superClassTypeElement;
|
||||
}
|
||||
// Failure; we reached the root without finding a subclass of EppException.
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Class referenced is not a subclass of %s", EXCEPTION_CLASS_NAME));
|
||||
}
|
||||
|
||||
/** Returns the corresponding EPP error code for an annotated subclass of EppException. */
|
||||
private long extractErrorCode(TypeElement typeElement) {
|
||||
try {
|
||||
// We're looking for a specific annotation by name that should appear only once.
|
||||
AnnotationMirror errorCodeAnnotation =
|
||||
typeElement.getAnnotationMirrors().stream()
|
||||
.filter(anno -> anno.getAnnotationType().toString().equals(CODE_ANNOTATION_NAME))
|
||||
.findFirst()
|
||||
.get();
|
||||
// The annotation should have one element whose value converts to an EppResult.Code.
|
||||
AnnotationValue value =
|
||||
errorCodeAnnotation.getElementValues().entrySet().iterator().next().getValue();
|
||||
return Code.valueOf(value.getValue().toString()).code;
|
||||
} catch (IllegalStateException e) {
|
||||
throw new IllegalStateException(
|
||||
"No error code annotation found on exception " + typeElement.getQualifiedName(), e);
|
||||
} catch (ArrayIndexOutOfBoundsException | ClassCastException | IllegalArgumentException e) {
|
||||
throw new IllegalStateException(
|
||||
"Bad annotation on exception " + typeElement.getQualifiedName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object object) {
|
||||
// The className field canonically identifies the EppException wrapped by this class, and
|
||||
// all other instance state is derived from that exception, so we only check className.
|
||||
return object instanceof ErrorCase && this.className.equals(((ErrorCase) object).className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// See note for equals() - only className is needed for comparisons.
|
||||
return className.hashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.io.Files;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tool to generate documentation for the EPP flows and corresponding external API.
|
||||
*
|
||||
* <p>Mostly responsible for producing standalone documentation files (HTML and Markdown) from flow
|
||||
* information objects; those call into javadoc to extract documentation information from the flows
|
||||
* package source files. See the {@link FlowDocumentation} class for more details.
|
||||
*/
|
||||
@Parameters(separators = " =", commandDescription = "Tool to generate EPP API documentation")
|
||||
public class FlowDocumentationTool {
|
||||
|
||||
@Parameter(
|
||||
names = {"-o", "--output_file"},
|
||||
description = "file where generated documentation will be written (use '-' for stdout)")
|
||||
private String outputFileName;
|
||||
|
||||
@Parameter(
|
||||
names = {"--help", "--helpshort"},
|
||||
description = "print this help",
|
||||
help = true)
|
||||
private boolean displayHelp = false;
|
||||
|
||||
/** Parses command line flags and then runs the documentation tool. */
|
||||
public static void main(String[] args) {
|
||||
FlowDocumentationTool docTool = new FlowDocumentationTool();
|
||||
JCommander jcommander = new JCommander(docTool);
|
||||
jcommander.setProgramName("flow_docs_tool");
|
||||
|
||||
try {
|
||||
jcommander.parse(args);
|
||||
} catch (ParameterException e) {
|
||||
jcommander.usage();
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (docTool.displayHelp) {
|
||||
jcommander.usage();
|
||||
return;
|
||||
}
|
||||
|
||||
docTool.run();
|
||||
}
|
||||
|
||||
/** Generates flow documentation and then outputs it to the specified file. */
|
||||
public void run() {
|
||||
DocumentationGenerator docGenerator;
|
||||
try {
|
||||
docGenerator = new DocumentationGenerator();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("IO error while running Javadoc tool", e);
|
||||
}
|
||||
String output = docGenerator.generateMarkdown();
|
||||
if (outputFileName.equals("-")) {
|
||||
System.out.println(output);
|
||||
} else {
|
||||
if (outputFileName == null) {
|
||||
outputFileName = "doclet.md";
|
||||
}
|
||||
try {
|
||||
Files.asCharSink(new File(outputFileName), UTF_8).write(output);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not write to specified output file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static google.registry.util.BuildPathUtils.getProjectRoot;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import javax.tools.StandardLocation;
|
||||
import jdk.javadoc.doclet.DocletEnvironment;
|
||||
import jdk.javadoc.internal.tool.AccessKind;
|
||||
import jdk.javadoc.internal.tool.JavadocTool;
|
||||
import jdk.javadoc.internal.tool.Messager;
|
||||
import jdk.javadoc.internal.tool.ToolOption;
|
||||
|
||||
/**
|
||||
* Wrapper class to simplify calls to the javadoc system and hide internal details. An instance
|
||||
* represents a set of parameters for calling out to javadoc; these parameters can be set via the
|
||||
* appropriate methods, and determine what files and packages javadoc will process. The actual
|
||||
* running of javadoc occurs when calling getRootDoc() to retrieve a javadoc RootDoc.
|
||||
*/
|
||||
public final class JavadocWrapper {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/** Shows any member visible at at least the default (package) level. */
|
||||
private static final AccessKind ACCESS_KIND = AccessKind.PACKAGE;
|
||||
|
||||
/** Root directory for source files. */
|
||||
public static final String SOURCE_PATH =
|
||||
getProjectRoot().resolve("core/src/main/java").toString();
|
||||
|
||||
/** Specific packages to generate documentation for. */
|
||||
private static final ImmutableList<String> SOURCE_PACKAGE_NAMES =
|
||||
ImmutableList.of(FlowDocumentation.FLOW_PACKAGE_NAME);
|
||||
|
||||
/**
|
||||
* Obtains a Javadoc {@link DocletEnvironment} object containing raw Javadoc documentation. Wraps
|
||||
* a call to the static method {@link #createDocletEnv} and passes in instance-specific settings.
|
||||
*/
|
||||
public static DocletEnvironment getDocletEnv() throws Exception {
|
||||
logger.atInfo().log("Starting Javadoc tool");
|
||||
File sourceFilePath = new File(SOURCE_PATH);
|
||||
logger.atInfo().log("Using source directory: %s", sourceFilePath.getAbsolutePath());
|
||||
try {
|
||||
return createDocletEnv(SOURCE_PATH, SOURCE_PACKAGE_NAMES);
|
||||
} finally {
|
||||
logger.atInfo().log("Javadoc tool finished");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a Javadoc {@link DocletEnvironment} object for the specified source path and
|
||||
* package/Java names. If the source path is null, then the working directory is assumed as the
|
||||
* source path.
|
||||
*
|
||||
* <p>If a list of package names is provided, then Javadoc will run on these packages and all
|
||||
* their subpackages, based out of the specified source path.
|
||||
*
|
||||
* <p>If a list of file names is provided, then Javadoc will also run on these Java source files.
|
||||
* The specified source path is not considered in this case.
|
||||
*
|
||||
* @param sourcePath the directory where to look for packages.
|
||||
* @param packageNames name of the package to run javadoc on, including subpackages.
|
||||
* @see <a
|
||||
* href="https://docs.oracle.com/javase/9/docs/api/jdk/javadoc/doclet/package-summary.html">
|
||||
* Package jdk.javadoc.doclet</a>
|
||||
*/
|
||||
private static DocletEnvironment createDocletEnv(
|
||||
String sourcePath, Collection<String> packageNames) throws Exception {
|
||||
|
||||
// Create a context to hold settings for Javadoc.
|
||||
Context context = new Context();
|
||||
|
||||
// Pre-register a messager for the context.
|
||||
Messager.preRegister(context, JavadocWrapper.class.getName());
|
||||
|
||||
// Set source path option for Javadoc.
|
||||
try (JavacFileManager fileManager = new JavacFileManager(context, true, UTF_8)) {
|
||||
|
||||
fileManager.setLocation(StandardLocation.SOURCE_PATH, ImmutableList.of(new File(sourcePath)));
|
||||
|
||||
// Create an instance of Javadoc.
|
||||
JavadocTool javadocTool = JavadocTool.make0(context);
|
||||
|
||||
// Set up javadoc tool options.
|
||||
Map<ToolOption, Object> options = new EnumMap<>(ToolOption.class);
|
||||
options.put(ToolOption.SHOW_PACKAGES, ACCESS_KIND);
|
||||
options.put(ToolOption.SHOW_TYPES, ACCESS_KIND);
|
||||
options.put(ToolOption.SHOW_MEMBERS, ACCESS_KIND);
|
||||
options.put(ToolOption.SHOW_MODULE_CONTENTS, ACCESS_KIND);
|
||||
options.put(ToolOption.SUBPACKAGES, packageNames);
|
||||
|
||||
// Invoke Javadoc and ask it for a DocletEnvironment containing the specified packages.
|
||||
return javadocTool.getEnvironment(
|
||||
options, // options
|
||||
ImmutableList.of(), // java names
|
||||
ImmutableList.of()); // java files
|
||||
}
|
||||
}
|
||||
|
||||
private JavadocWrapper() {}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.documentation.FlowDocumentation.ErrorCase;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Formatter that converts flow documentation into Markdown. */
|
||||
public final class MarkdownDocumentationFormatter {
|
||||
|
||||
/** Header for flow documentation HTML output. */
|
||||
private static final String MARKDOWN_HEADER = "# Nomulus EPP Command API Documentation\n\n";
|
||||
|
||||
/** Pattern that naively matches HTML tags and entity references. */
|
||||
private static final Pattern HTML_TAG_AND_ENTITY_PATTERN = Pattern.compile("<[^>]*>|&[^;]*;");
|
||||
|
||||
/** 8 character indentation. */
|
||||
private static final String INDENT8 = Strings.repeat(" ", 8);
|
||||
|
||||
/** Max linewidth for our markdown docs. */
|
||||
private static final int LINE_WIDTH = 80;
|
||||
|
||||
/**
|
||||
* Returns the string with all HTML tags stripped. Also, removes a single space after any newlines
|
||||
* that have one (we get a single space indent for all lines but the first because of the way that
|
||||
* javadocs are written in comments).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String fixHtml(String value) {
|
||||
Matcher matcher = HTML_TAG_AND_ENTITY_PATTERN.matcher(value);
|
||||
int pos = 0;
|
||||
StringBuilder result = new StringBuilder();
|
||||
while (matcher.find(pos)) {
|
||||
result.append(value, pos, matcher.start());
|
||||
switch (matcher.group(0)) {
|
||||
case "<p>":
|
||||
// <p> is simply removed.
|
||||
break;
|
||||
case "&":
|
||||
result.append("&");
|
||||
break;
|
||||
case "<":
|
||||
result.append("<");
|
||||
break;
|
||||
case ">":
|
||||
result.append(">");
|
||||
break;
|
||||
case "&squot;":
|
||||
result.append("'");
|
||||
break;
|
||||
case """:
|
||||
result.append("\"");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized HTML sequence: " + matcher.group(0));
|
||||
}
|
||||
pos = matcher.end();
|
||||
}
|
||||
|
||||
// Add the string after the last HTML sequence.
|
||||
result.append(value.substring(pos));
|
||||
|
||||
return result.toString().replace("\n ", "\n");
|
||||
}
|
||||
|
||||
/** Formats a list of words into a paragraph with less than maxWidth characters per line. */
|
||||
@VisibleForTesting
|
||||
static String formatParagraph(List<String> words, int maxWidth) {
|
||||
int lineLength = 0;
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
for (String word : words) {
|
||||
// This check ensures that 1) don't add a space before the word and 2) always have at least
|
||||
// one word per line, so that we don't mishandle a very long word at the end of a line by
|
||||
// adding a blank line before the word.
|
||||
if (lineLength > 0) {
|
||||
// Do we have enough room for another word?
|
||||
if (lineLength + 1 + word.length() > maxWidth) {
|
||||
// No. End the line.
|
||||
output.append('\n');
|
||||
lineLength = 0;
|
||||
} else {
|
||||
// Yes: Insert a space before the word.
|
||||
output.append(' ');
|
||||
++lineLength;
|
||||
}
|
||||
}
|
||||
|
||||
output.append(word);
|
||||
lineLength += word.length();
|
||||
}
|
||||
|
||||
output.append('\n');
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/** Returns 'value' with words reflowed to maxWidth characters. */
|
||||
@VisibleForTesting
|
||||
static String reflow(String text, int maxWidth) {
|
||||
|
||||
// A list of words that will be constructed into the list of words in a paragraph.
|
||||
ArrayList<String> words = new ArrayList<>();
|
||||
|
||||
// Read through the lines, process a paragraph every time we get a blank line.
|
||||
StringBuilder resultBuilder = new StringBuilder();
|
||||
for (String line : Splitter.on('\n').trimResults().split(text)) {
|
||||
|
||||
// If we got a blank line, format our current paragraph and start fresh.
|
||||
if (line.trim().isEmpty()) {
|
||||
resultBuilder.append(formatParagraph(words, maxWidth));
|
||||
resultBuilder.append('\n');
|
||||
words.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Split the line into words and add them to the current paragraph.
|
||||
words.addAll(
|
||||
Splitter.on(CharMatcher.breakingWhitespace()).omitEmptyStrings().splitToList(line));
|
||||
}
|
||||
|
||||
// Format the last paragraph, if any.
|
||||
if (!words.isEmpty()) {
|
||||
resultBuilder.append(formatParagraph(words, maxWidth));
|
||||
}
|
||||
|
||||
return resultBuilder.toString();
|
||||
}
|
||||
|
||||
/** Returns a string of HTML representing the provided flow documentation objects. */
|
||||
public static String generateMarkdownOutput(Iterable<FlowDocumentation> flowDocs) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append(MARKDOWN_HEADER);
|
||||
for (FlowDocumentation flowDoc : flowDocs) {
|
||||
output.append(String.format("## %s\n\n", flowDoc.getName()));
|
||||
output.append("### Description\n\n");
|
||||
output.append(String.format("%s\n", reflow(fixHtml(flowDoc.getDocTree()), LINE_WIDTH)));
|
||||
output.append("### Errors\n\n");
|
||||
for (Long code : flowDoc.getErrorsByCode().keySet()) {
|
||||
output.append(String.format("* %d\n", code));
|
||||
|
||||
flowDoc.getErrorsByCode().get(code).stream()
|
||||
.map(ErrorCase::getReason)
|
||||
.distinct()
|
||||
.forEach(
|
||||
reason -> {
|
||||
output.append(" * ");
|
||||
String wrappedReason = reflow(fixHtml(reason), LINE_WIDTH - 8);
|
||||
|
||||
// Replace internal newlines with indentation and strip the final newline.
|
||||
output.append(wrappedReason.trim().replace("\n", "\n" + INDENT8));
|
||||
output.append('\n');
|
||||
});
|
||||
}
|
||||
output.append('\n');
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
private MarkdownDocumentationFormatter() {}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
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 com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static google.registry.util.BuildPathUtils.getProjectRoot;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.thoughtworks.qdox.JavaDocBuilder;
|
||||
import com.thoughtworks.qdox.model.JavaSource;
|
||||
import google.registry.documentation.FlowDocumentation.ErrorCase;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Stores the context for a flow and computes exception mismatches between javadoc and tests.
|
||||
*
|
||||
* <p>This class uses the flow_docs library built for the documentation generator tool to pull out
|
||||
* the set of flow exceptions documented by custom javadoc tags on the specified flow. It then
|
||||
* derives the corresponding test files for that flow and pulls out the imported names from those
|
||||
* files, checking against a set of all possible flow exceptions to determine those used by this
|
||||
* particular test. The set of javadoc-based exceptions and the set of imported exceptions should
|
||||
* be identical, ensuring a correspondence between error cases listed in the documentation and
|
||||
* those tested in the flow unit tests.
|
||||
*
|
||||
* <p>If the two sets are not identical, the getMismatchedExceptions() method on this class will
|
||||
* return a non-empty string containing messages about what the mismatches were and which lines
|
||||
* need to be added or removed in which files in order to satisfy the correspondence condition.
|
||||
*/
|
||||
public class FlowContext {
|
||||
/** Represents one of the two possible places an exception may be referenced from. */
|
||||
// TODO(b/19124943): This enum is only used in ErrorCaseMismatch and ideally belongs there, but
|
||||
// can't go in the inner class because it's not a static inner class. At some point it might
|
||||
// be worth refactoring so that this enum can be properly scoped.
|
||||
private enum SourceType { JAVADOC, IMPORT }
|
||||
|
||||
/** The package in which this flow resides. */
|
||||
final String packageName;
|
||||
|
||||
/** The source file for this flow, used for help messages. */
|
||||
final String sourceFilename;
|
||||
|
||||
/** The test files for this flow, used for help messages and extracting imported exceptions. */
|
||||
final Set<String> testFilenames;
|
||||
|
||||
/** The set of all possible exceptions that could be error cases for a flow. */
|
||||
final Set<ErrorCase> possibleExceptions;
|
||||
|
||||
/** The set of exceptions referenced from the javadoc on this flow. */
|
||||
final Set<ErrorCase> javadocExceptions;
|
||||
|
||||
/** Maps exceptions imported by the test files for this flow to the files in which they occur. */
|
||||
final SetMultimap<ErrorCase, String> importExceptionsToFilenames;
|
||||
|
||||
/**
|
||||
* Creates a FlowContext from a FlowDocumentation object and a set of all possible exceptions.
|
||||
* The latter parameter is needed in order to filter imported names in the flow test file.
|
||||
*/
|
||||
public FlowContext(FlowDocumentation flowDoc, Set<ErrorCase> possibleExceptions)
|
||||
throws IOException {
|
||||
packageName = flowDoc.getPackageName();
|
||||
// Assume the standard filename conventions for locating the flow class's source file.
|
||||
sourceFilename = "java/" + flowDoc.getQualifiedName().replace('.', '/') + ".java";
|
||||
testFilenames = getTestFilenames(flowDoc.getQualifiedName());
|
||||
checkState(testFilenames.size() >= 1, "No test files found for %s.", flowDoc.getName());
|
||||
this.possibleExceptions = possibleExceptions;
|
||||
javadocExceptions = Sets.newHashSet(flowDoc.getErrors());
|
||||
importExceptionsToFilenames = getImportExceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to locate test files for this flow by looking in src/test/java/ for all files with the
|
||||
* exact same relative filename as the flow file, but with a "*Test{,Case}.java" suffix.
|
||||
*/
|
||||
private static Set<String> getTestFilenames(String flowName) throws IOException {
|
||||
String commonPrefix =
|
||||
getProjectRoot().resolve("core/src/test/java").resolve(flowName.replace('.', '/'))
|
||||
.toString();
|
||||
return Sets.union(
|
||||
getFilenamesMatchingGlob(commonPrefix + "*Test.java"),
|
||||
getFilenamesMatchingGlob(commonPrefix + "*TestCase.java"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to return the set of filenames matching the given glob. The glob should only have
|
||||
* asterisks in the portion following the last slash (if there is one).
|
||||
*/
|
||||
private static Set<String> getFilenamesMatchingGlob(String fullGlob) throws IOException {
|
||||
Path globPath = FileSystems.getDefault().getPath(fullGlob);
|
||||
Path dirPath = globPath.getParent();
|
||||
String glob = globPath.getFileName().toString();
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dirPath, glob)) {
|
||||
return Streams.stream(dirStream).map(Object::toString).collect(toImmutableSet());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a multimap mapping each exception imported in test files for this flow to the set of
|
||||
* filenames for files that import that exception.
|
||||
*/
|
||||
private SetMultimap<ErrorCase, String> getImportExceptions() throws IOException {
|
||||
ImmutableMultimap.Builder<String, ErrorCase> builder = new ImmutableMultimap.Builder<>();
|
||||
for (String testFileName : testFilenames) {
|
||||
builder.putAll(testFileName, getImportExceptionsFromFile(testFileName));
|
||||
}
|
||||
// Invert the mapping so that later we can easily map exceptions to where they were imported.
|
||||
return MultimapBuilder.hashKeys().hashSetValues().build(builder.build().inverse());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of exceptions imported in this test file. First extracts the set of
|
||||
* all names imported by the test file, and then uses these to filter a global list of possible
|
||||
* exceptions, so that the additional exception information available via the global list objects
|
||||
* (which are ErrorCases wrapping exception names) can be preserved.
|
||||
*/
|
||||
private Set<ErrorCase> getImportExceptionsFromFile(String filename) throws IOException {
|
||||
JavaDocBuilder builder = new JavaDocBuilder();
|
||||
JavaSource src = builder.addSource(new File(filename));
|
||||
final Set<String> importedNames = Sets.newHashSet(src.getImports());
|
||||
return possibleExceptions
|
||||
.stream()
|
||||
.filter(errorCase -> importedNames.contains(errorCase.getClassName()))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a mismatch in this flow for a specific error case and documents how to fix it.
|
||||
* A mismatch occurs when the exception for this error case appears in either the source file
|
||||
* javadoc or at least one matching test file, but not in both.
|
||||
*/
|
||||
private class ErrorCaseMismatch {
|
||||
|
||||
/** The format for an import statement for a given exception name. */
|
||||
static final String IMPORT_FORMAT = "import %s;";
|
||||
|
||||
/** The format for a javadoc tag referencing a given exception name. */
|
||||
static final String JAVADOC_FORMAT = "@error {@link %s}";
|
||||
|
||||
// Template strings for printing output.
|
||||
static final String TEMPLATE_HEADER = "Extra %s for %s:\n";
|
||||
static final String TEMPLATE_ADD = " Add %s to %s:\n + %s\n";
|
||||
static final String TEMPLATE_ADD_MULTIPLE = " Add %s to one or more of:\n%s + %s\n";
|
||||
static final String TEMPLATE_REMOVE = " Or remove %s in %s:\n - %s\n";
|
||||
static final String TEMPLATE_REMOVE_MULTIPLE = " Or remove %ss in:\n%s - %s\n";
|
||||
static final String TEMPLATE_MULTIPLE_FILES = " * %s\n";
|
||||
|
||||
/** The error case for which the mismatch was detected. */
|
||||
final ErrorCase errorCase;
|
||||
|
||||
/** The source type where references could be added to fix the mismatch. */
|
||||
final SourceType addType;
|
||||
|
||||
/** The source type where references could be removed to fix the mismatch. */
|
||||
final SourceType removeType;
|
||||
|
||||
/**
|
||||
* Constructs an ErrorCaseMismatch for the given ErrorCase and SourceType. The latter parameter
|
||||
* indicates the source type this exception was referenced from.
|
||||
*/
|
||||
public ErrorCaseMismatch(ErrorCase errorCase, SourceType foundType) {
|
||||
this.errorCase = errorCase;
|
||||
// Effectively addType = !foundType.
|
||||
addType = (foundType == SourceType.IMPORT ? SourceType.JAVADOC : SourceType.IMPORT);
|
||||
removeType = foundType;
|
||||
}
|
||||
|
||||
/** Returns the line of code needed to refer to this exception from the given source type. */
|
||||
public String getCodeLineAs(SourceType sourceType) {
|
||||
return sourceType == SourceType.JAVADOC
|
||||
// Strip the flow package prefix from the exception class name if possible, for brevity.
|
||||
? String.format(JAVADOC_FORMAT, errorCase.getClassName().replace(packageName + ".", ""))
|
||||
: String.format(IMPORT_FORMAT, errorCase.getClassName());
|
||||
}
|
||||
|
||||
/** Helper to format a set of filenames for printing in a mismatch message. */
|
||||
private String formatMultipleFiles(Set<String> filenames) {
|
||||
checkArgument(filenames.size() >= 1, "Cannot format empty list of files.");
|
||||
if (filenames.size() == 1) {
|
||||
return filenames.stream().collect(onlyElement());
|
||||
}
|
||||
return filenames
|
||||
.stream()
|
||||
.map(filename -> String.format(TEMPLATE_MULTIPLE_FILES, filename))
|
||||
.collect(joining(""));
|
||||
}
|
||||
|
||||
/** Helper to format the section describing how to add references to fix the mismatch. */
|
||||
private String makeAddSection() {
|
||||
String addTypeString = Ascii.toLowerCase(addType.toString());
|
||||
String codeLine = getCodeLineAs(addType);
|
||||
Set<String> files = (addType == SourceType.JAVADOC
|
||||
? ImmutableSet.of(sourceFilename)
|
||||
: testFilenames);
|
||||
return (files.size() == 1
|
||||
? String.format(
|
||||
TEMPLATE_ADD, addTypeString, formatMultipleFiles(files), codeLine)
|
||||
: String.format(
|
||||
TEMPLATE_ADD_MULTIPLE, addTypeString, formatMultipleFiles(files), codeLine));
|
||||
}
|
||||
|
||||
/** Helper to format the section describing how to remove references to fix the mismatch. */
|
||||
// TODO(b/19124943): Repeating structure from makeAddSection() - would be nice to clean up.
|
||||
private String makeRemoveSection() {
|
||||
String removeTypeString = Ascii.toLowerCase(removeType.toString());
|
||||
String codeLine = getCodeLineAs(removeType);
|
||||
Set<String> files = (removeType == SourceType.JAVADOC
|
||||
? ImmutableSet.of(sourceFilename)
|
||||
: importExceptionsToFilenames.get(errorCase));
|
||||
return (files.size() == 1
|
||||
? String.format(
|
||||
TEMPLATE_REMOVE, removeTypeString, formatMultipleFiles(files), codeLine)
|
||||
: String.format(
|
||||
TEMPLATE_REMOVE_MULTIPLE, removeTypeString, formatMultipleFiles(files), codeLine));
|
||||
}
|
||||
|
||||
/** Returns a string describing the mismatch for this flow exception and how to fix it. */
|
||||
@Override
|
||||
public String toString() {
|
||||
String headerSection = String.format(
|
||||
TEMPLATE_HEADER, Ascii.toLowerCase(removeType.toString()), errorCase.getName());
|
||||
return headerSection + makeAddSection() + makeRemoveSection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single string describing all mismatched exceptions for this flow. An empty string
|
||||
* means no mismatched exceptions were found.
|
||||
*/
|
||||
public String getMismatchedExceptions() {
|
||||
Set<ErrorCase> importExceptions = importExceptionsToFilenames.keySet();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (ErrorCase errorCase : Sets.difference(javadocExceptions, importExceptions)) {
|
||||
builder.append(new ErrorCaseMismatch(errorCase, SourceType.JAVADOC)).append("\n");
|
||||
}
|
||||
for (ErrorCase errorCase : Sets.difference(importExceptions, javadocExceptions)) {
|
||||
builder.append(new ErrorCaseMismatch(errorCase, SourceType.IMPORT)).append("\n");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static google.registry.util.BuildPathUtils.getProjectRoot;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests to ensure that generated flow documentation matches the expected documentation. */
|
||||
class FlowDocumentationTest {
|
||||
private static final Path GOLDEN_MARKDOWN_FILEPATH = getProjectRoot().resolve("docs/flows.md");
|
||||
|
||||
private static final String UPDATE_COMMAND = "./gradlew :docs:flowDocsTool";
|
||||
private static final String UPDATE_INSTRUCTIONS =
|
||||
Joiner.on('\n')
|
||||
.join(
|
||||
"",
|
||||
"-----------------------------------------------------------------------------------",
|
||||
"Your changes affect the flow API documentation output. To update the golden version "
|
||||
+ "of the documentation, run:",
|
||||
UPDATE_COMMAND,
|
||||
"");
|
||||
|
||||
@Test
|
||||
void testGeneratedMatchesGolden() throws Exception {
|
||||
// Read the markdown file.
|
||||
String goldenMarkdown = Files.readString(GOLDEN_MARKDOWN_FILEPATH);
|
||||
|
||||
// Don't use Truth's isEqualTo() because the output is huge and unreadable for large files.
|
||||
DocumentationGenerator generator = new DocumentationGenerator();
|
||||
if (!generator.generateMarkdown().equals(goldenMarkdown)) {
|
||||
assertWithMessage(UPDATE_INSTRUCTIONS).fail();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.documentation.FlowDocumentation.ErrorCase;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test to ensure accurate documentation of flow exceptions.
|
||||
*
|
||||
* <p>This test goes through each flow and ensures that the exceptions listed in custom javadoc
|
||||
* tags on the flow class match the import statements in the test case for that flow. Thus it
|
||||
* catches the case where someone adds a test case for an exception without updating the javadoc,
|
||||
* and the case where someone adds a javadoc tag to a flow without writing a test for this error
|
||||
* condition. For example, there should always be a matching pair of lines such as the following:
|
||||
*
|
||||
* <pre>
|
||||
* src/main/java/.../flows/session/LoginFlow.java:
|
||||
* @error {@link AlreadyLoggedInException}
|
||||
*
|
||||
* src/test/java/.../flows/session/LoginFlowTest.java:
|
||||
* import .....flows.session.LoginFlow.AlreadyLoggedInException;
|
||||
* </pre>
|
||||
*
|
||||
* If the first line is missing, this test fails and suggests adding the javadoc tag or removing
|
||||
* the import. If the second line is missing, this test fails and suggests adding the import or
|
||||
* removing the javadoc tag.
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
class FlowExceptionsTest {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Test
|
||||
void testExceptionCorrespondence() throws Exception {
|
||||
DocumentationGenerator docGenerator = new DocumentationGenerator();
|
||||
Set<ErrorCase> possibleErrors = Sets.newHashSet(docGenerator.getAllErrors());
|
||||
Set<String> mismatchingFlows = Sets.newHashSet();
|
||||
for (FlowDocumentation flow : docGenerator.getFlowDocs()) {
|
||||
FlowContext context = new FlowContext(flow, possibleErrors);
|
||||
String mismatches = context.getMismatchedExceptions();
|
||||
if (!mismatches.isEmpty()) {
|
||||
logger.atWarning().log("%-40s FAIL\n\n%s", flow.getName(), mismatches);
|
||||
mismatchingFlows.add(flow.getName());
|
||||
} else {
|
||||
logger.atInfo().log("%-40s OK", flow.getName());
|
||||
}
|
||||
}
|
||||
assertWithMessage(
|
||||
"Mismatched exceptions between flow documentation and tests. See test log for full "
|
||||
+ "details. The set of failing flows follows.")
|
||||
.that(mismatchingFlows)
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright 2017 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.documentation;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Test conversion of javadocs to markdown. */
|
||||
class MarkdownDocumentationFormatterTest {
|
||||
|
||||
@Test
|
||||
void testHtmlSanitization() {
|
||||
assertThat(
|
||||
MarkdownDocumentationFormatter.fixHtml(
|
||||
"First. <p>Second. < > & &squot; ""))
|
||||
.isEqualTo("First. Second. < > & ' \"");
|
||||
assertThat(MarkdownDocumentationFormatter.fixHtml("<p>Leading substitution."))
|
||||
.isEqualTo("Leading substitution.");
|
||||
assertThat(MarkdownDocumentationFormatter.fixHtml("No substitution."))
|
||||
.isEqualTo("No substitution.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDedents() {
|
||||
assertThat(
|
||||
MarkdownDocumentationFormatter.fixHtml("First line\n\n <p>Second line.\n Third line."))
|
||||
.isEqualTo("First line\n\nSecond line.\nThird line.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnknownSequences() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () -> MarkdownDocumentationFormatter.fixHtml("&blech;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParagraphFormatting() {
|
||||
String[] words = {"first", "second", "third", "really-really-long-word", "more", "stuff"};
|
||||
String formatted = MarkdownDocumentationFormatter.formatParagraph(Arrays.asList(words), 16);
|
||||
assertThat(formatted).isEqualTo("first second\nthird\nreally-really-long-word\nmore stuff\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReflow() {
|
||||
String input =
|
||||
"This is the very first line.\n"
|
||||
+ " \n" // add a little blank space to this line just to make things interesting.
|
||||
+ "This is the second paragraph. Aint\n"
|
||||
+ "it sweet?\n"
|
||||
+ "\n"
|
||||
+ "This is our third and final paragraph.\n"
|
||||
+ "It is multi-line and ends with no blank\n"
|
||||
+ "line.";
|
||||
|
||||
String expected =
|
||||
"This is the very\n"
|
||||
+ "first line.\n"
|
||||
+ "\n"
|
||||
+ "This is the\n"
|
||||
+ "second\n"
|
||||
+ "paragraph. Aint\n"
|
||||
+ "it sweet?\n"
|
||||
+ "\n"
|
||||
+ "This is our\n"
|
||||
+ "third and final\n"
|
||||
+ "paragraph. It is\n"
|
||||
+ "multi-line and\n"
|
||||
+ "ends with no\n"
|
||||
+ "blank line.\n";
|
||||
|
||||
assertThat(MarkdownDocumentationFormatter.reflow(input, 16)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
MarkdownDocumentationFormatterTest() {}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue