diff --git a/.kokoro/build.sh b/.kokoro/build.sh new file mode 100755 index 000000000..dad012856 --- /dev/null +++ b/.kokoro/build.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +cd github/api-common-java/ + +# Print out Java +java -version +echo $JOB_TYPE + +./gradlew assemble +./gradlew build install + +bash $KOKORO_GFILE_DIR/codecov.sh diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg new file mode 100644 index 000000000..f10834a28 --- /dev/null +++ b/.kokoro/common.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Download trampoline resources. These will be in ${KOKORO_GFILE_DIR} +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# All builds use the trampoline script to run in docker. +build_file: "api-common-java/.kokoro/trampoline.sh" + +# Tell the trampoline which build file to use. +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/build.sh" +} diff --git a/.kokoro/continuous/common.cfg b/.kokoro/continuous/common.cfg new file mode 100644 index 000000000..1c23fa586 --- /dev/null +++ b/.kokoro/continuous/common.cfg @@ -0,0 +1,24 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "api-common-java/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "test" +} diff --git a/.kokoro/continuous/java11.cfg b/.kokoro/continuous/java11.cfg new file mode 100644 index 000000000..709f2b4c7 --- /dev/null +++ b/.kokoro/continuous/java11.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} diff --git a/.kokoro/continuous/java7.cfg b/.kokoro/continuous/java7.cfg new file mode 100644 index 000000000..cb24f44ee --- /dev/null +++ b/.kokoro/continuous/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/.kokoro/continuous/java8.cfg b/.kokoro/continuous/java8.cfg new file mode 100644 index 000000000..3b017fc80 --- /dev/null +++ b/.kokoro/continuous/java8.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/.kokoro/presubmit/common.cfg b/.kokoro/presubmit/common.cfg new file mode 100644 index 000000000..1c23fa586 --- /dev/null +++ b/.kokoro/presubmit/common.cfg @@ -0,0 +1,24 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "api-common-java/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "test" +} diff --git a/.kokoro/presubmit/java11.cfg b/.kokoro/presubmit/java11.cfg new file mode 100644 index 000000000..709f2b4c7 --- /dev/null +++ b/.kokoro/presubmit/java11.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} diff --git a/.kokoro/presubmit/java7.cfg b/.kokoro/presubmit/java7.cfg new file mode 100644 index 000000000..cb24f44ee --- /dev/null +++ b/.kokoro/presubmit/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/.kokoro/presubmit/java8.cfg b/.kokoro/presubmit/java8.cfg new file mode 100644 index 000000000..3b017fc80 --- /dev/null +++ b/.kokoro/presubmit/java8.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg new file mode 100644 index 000000000..c22ce6933 --- /dev/null +++ b/.kokoro/release/common.cfg @@ -0,0 +1,49 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "api-common-java/.kokoro/trampoline.sh" + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-keyring" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-passphrase" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-pubkeyring" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "sonatype-credentials" + } + } +} diff --git a/.kokoro/release/common.sh b/.kokoro/release/common.sh new file mode 100755 index 000000000..d5738d430 --- /dev/null +++ b/.kokoro/release/common.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +# Get secrets from keystore and set and environment variables +setup_environment_secrets() { + export GPG_PASSPHRASE=$(cat ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-passphrase) + export GPG_TTY=$(tty) + export GPG_HOMEDIR=/gpg + mkdir $GPG_HOMEDIR + mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-pubkeyring $GPG_HOMEDIR/pubring.gpg + mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-keyring $GPG_HOMEDIR/secring.gpg + export GPG_KEY_ID=$(echo -n $(gpg --with-colons ${GPG_HOMEDIR}/pubring.gpg | awk -F':' '/pub/{ print $5 }')) + export SONATYPE_USERNAME=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f1 -d'|') + export SONATYPE_PASSWORD=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f2 -d'|') +} + +create_gradle_properties_file() { + echo " +signing.gnupg.executable=gpg +signing.gnupg.homeDir=${GPG_HOMEDIR} +signing.gnupg.keyName=${GPG_KEY_ID} +signing.gnupg.passphrase=${GPG_PASSPHRASE} + +ossrhUsername=${SONATYPE_USERNAME} +ossrhPassword=${SONATYPE_PASSWORD}" > $1 +} diff --git a/.kokoro/release/drop.cfg b/.kokoro/release/drop.cfg new file mode 100644 index 000000000..feb878972 --- /dev/null +++ b/.kokoro/release/drop.cfg @@ -0,0 +1,5 @@ +# Format: //devtools/kokoro/config/proto/build.proto + env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/release/drop.sh" +} diff --git a/.kokoro/release/drop.sh b/.kokoro/release/drop.sh new file mode 100755 index 000000000..ce6ae7543 --- /dev/null +++ b/.kokoro/release/drop.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +echo "This dropping a staged repo does not appear supported by the gradle-nexus-staging-plugin" +exit 1 diff --git a/.kokoro/release/promote.cfg b/.kokoro/release/promote.cfg new file mode 100644 index 000000000..d69f1d6f2 --- /dev/null +++ b/.kokoro/release/promote.cfg @@ -0,0 +1,5 @@ +# Format: //devtools/kokoro/config/proto/build.proto + env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/release/promote.sh" +} diff --git a/.kokoro/release/promote.sh b/.kokoro/release/promote.sh new file mode 100755 index 000000000..2dcfd256d --- /dev/null +++ b/.kokoro/release/promote.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +# STAGING_REPOSITORY_ID must be set +#if [ -z "${STAGING_REPOSITORY_ID}" ]; then +# echo "Missing STAGING_REPOSITORY_ID environment variable" +# exit 1 +#fi + +source $(dirname "$0")/common.sh +pushd $(dirname "$0")/../../ + +setup_environment_secrets +mkdir -p ${HOME}/.gradle +create_gradle_properties_file "${HOME}/.gradle/gradle.properties" + +./gradlew closeAndReleaseRepository diff --git a/.kokoro/release/publish_javadoc.cfg b/.kokoro/release/publish_javadoc.cfg new file mode 100644 index 000000000..043f92f13 --- /dev/null +++ b/.kokoro/release/publish_javadoc.cfg @@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto +env_vars: { + key: "STAGING_BUCKET" + value: "docs-staging" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/release/publish_javadoc.sh" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "docuploader_service_account" + } + } +} diff --git a/.kokoro/release/publish_javadoc.sh b/.kokoro/release/publish_javadoc.sh new file mode 100755 index 000000000..09e830704 --- /dev/null +++ b/.kokoro/release/publish_javadoc.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +if [[ -z "${CREDENTIALS}" ]]; then + CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account +fi + +if [[ -z "${STAGING_BUCKET}" ]]; then + echo "Need to set STAGING_BUCKET environment variable" + exit 1 +fi + +# work from the git root directory +pushd $(dirname "$0")/../../ + +# install docuploader package +python3 -m pip install gcp-docuploader + +NAME=api-common +VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) + +# build the docs +./gradlew javadocCombined + +pushd tmp_docs + +# create metadata +python3 -m docuploader create-metadata \ + --name ${NAME} \ + --version ${VERSION} \ + --language java + +# upload docs +python3 -m docuploader upload . \ + --credentials ${CREDENTIALS} \ + --staging-bucket ${STAGING_BUCKET} + +popd diff --git a/.kokoro/release/stage.cfg b/.kokoro/release/stage.cfg new file mode 100644 index 000000000..4016988c9 --- /dev/null +++ b/.kokoro/release/stage.cfg @@ -0,0 +1,35 @@ +# Format: //devtools/kokoro/config/proto/build.proto + env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/api-common-java/.kokoro/release/stage.sh" +} + +# Fetch the token needed for reporting release status to GitHub +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "yoshi-automation-github-key" + } + } +} + +# Fetch magictoken to use with Magic Github Proxy +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "releasetool-magictoken" + } + } +} + +# Fetch api key to use with Magic Github Proxy +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "magic-github-proxy-api-key" + } + } +} diff --git a/.kokoro/release/stage.sh b/.kokoro/release/stage.sh new file mode 100755 index 000000000..f927ce143 --- /dev/null +++ b/.kokoro/release/stage.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +if [[ -n "${AUTORELEASE_PR}" ]] +then + # Start the releasetool reporter + python3 -m pip install gcp-releasetool + python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script +fi + +source $(dirname "$0")/common.sh +MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml +pushd $(dirname "$0")/../../ + +setup_environment_secrets +mkdir -p ${HOME}/.gradle +create_gradle_properties_file "${HOME}/.gradle/gradle.properties" + +./gradlew assemble uploadArchives + +if [[ -n "${AUTORELEASE_PR}" ]] +then + ./gradlew closeAndReleaseRepository +fi diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh new file mode 100755 index 000000000..3e90f6494 --- /dev/null +++ b/.kokoro/trampoline.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. +set -eo pipefail +# Always run the cleanup script, regardless of the success of bouncing into +# the container. +function cleanup() { + chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + echo "cleanup"; +} +trap cleanup EXIT +python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" diff --git a/.travis.yml b/.travis.yml index 98fb50e41..2e07a726e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: false -dist: precise +dist: trusty language: java addons: # https://github.com/travis-ci/travis-ci/issues/5227#issuecomment-165131913 @@ -8,8 +8,7 @@ addons: hostname: fake-hostname-to-work-around-travis-bug jdk: - oraclejdk8 - - oraclejdk7 - - openjdk7 + - openjdk8 script: ./gradlew check --info after_success: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2827b7d3f..c6877c550 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,5 @@ +# How to Contribute + Want to contribute? Great! First, read this page (including the small print at the end). ### Before you contribute diff --git a/build.gradle b/build.gradle index d95645ed6..b4e410765 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,8 @@ buildscript { jcenter() } dependencies { - classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.6", - "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.8.0" + classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.8", + "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.21.2" } } @@ -39,19 +39,16 @@ ext { // Shortcuts for libraries we are using libraries = [ javax_annotations: 'javax.annotation:javax.annotation-api:1.3.2', - guava: 'com.google.guava:guava:26.0-android', + auto_value_annotations: 'com.google.auto.value:auto-value-annotations:1.7', + auto_value: 'com.google.auto.value:auto-value:1.7', + guava: 'com.google.guava:guava:28.2-android', jsr305: 'com.google.code.findbugs:jsr305:3.0.2', - autovalue: 'com.google.auto.value:auto-value:1.1', - error_prone_annotations: 'com.google.errorprone:error_prone_annotations:2.3.2', + error_prone_annotations: 'com.google.errorprone:error_prone_annotations:2.3.4', // Testing - junit: 'junit:junit:4.12', + junit: 'junit:junit:4.13', mockito: 'org.mockito:mockito-core:1.10.19', - truth: 'com.google.truth:truth:0.42', - commons: 'org.apache.commons:commons-lang3:3.5', - - // Formatter - javaFomatter: 'com.google.googlejavaformat:google-java-format:0.1-alpha' + truth: 'com.google.truth:truth:1.0.1', ] } @@ -61,17 +58,19 @@ repositories { } dependencies { + + annotationProcessor libraries.auto_value + compile libraries.guava, libraries.jsr305, - libraries.javax_annotations + libraries.javax_annotations, + libraries.auto_value_annotations - compileOnly libraries.autovalue, - libraries.error_prone_annotations + compileOnly libraries.error_prone_annotations testCompile libraries.junit, libraries.mockito, - libraries.truth, - libraries.commons + libraries.truth } clean.doFirst { @@ -139,9 +138,8 @@ configurations { } dependencies { - codeGeneration libraries.autovalue, libraries.jsr305 - compile libraries.jsr305 - compileOnly libraries.autovalue + codeGeneration libraries.auto_value, libraries.jsr305 + compile libraries.jsr305, libraries.auto_value_annotations } compileJava.classpath += configurations.codeGeneration @@ -195,6 +193,9 @@ artifacts { signing { required { gradle.taskGraph.hasTask("uploadArchives") } + if (project.hasProperty('signing.gnupg.executable')) { + useGpgCmd() + } sign configurations.archives } @@ -237,7 +238,7 @@ if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword') name 'GoogleAPIs' email 'googleapis@googlegroups.com' url 'https://github.com/googleapis' - organization 'Google, Inc.' + organization = 'Google, Inc.' organizationUrl 'https://www.google.com' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84c977200..f6fd8db47 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-4.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..f45d8f110 --- /dev/null +++ b/renovate.json @@ -0,0 +1,5 @@ +{ + "extends": [ + "config:base" + ] +} diff --git a/src/main/java/com/google/api/core/ApiFutures.java b/src/main/java/com/google/api/core/ApiFutures.java index d0638f1f6..d02892619 100644 --- a/src/main/java/com/google/api/core/ApiFutures.java +++ b/src/main/java/com/google/api/core/ApiFutures.java @@ -104,6 +104,27 @@ public static ApiFuture catching( return new ListenableFutureToApiFuture(catchingFuture); } + @BetaApi + public static ApiFuture catchingAsync( + ApiFuture input, + Class exceptionType, + final ApiAsyncFunction callback, + Executor executor) { + ListenableFuture catchingFuture = + Futures.catchingAsync( + listenableFutureForApiFuture(input), + exceptionType, + new AsyncFunction() { + @Override + public ListenableFuture apply(X exception) throws Exception { + ApiFuture result = callback.apply(exception); + return listenableFutureForApiFuture(result); + } + }, + executor); + return new ListenableFutureToApiFuture<>(catchingFuture); + } + public static ApiFuture immediateFuture(V value) { return new ListenableFutureToApiFuture<>(Futures.immediateFuture(value)); } diff --git a/src/test/java/com/google/api/core/ApiFuturesTest.java b/src/test/java/com/google/api/core/ApiFuturesTest.java index eec0fd8f3..de10b7ee8 100644 --- a/src/test/java/com/google/api/core/ApiFuturesTest.java +++ b/src/test/java/com/google/api/core/ApiFuturesTest.java @@ -83,6 +83,24 @@ public Integer apply(Exception ex) { assertThat(fallback.get()).isEqualTo(42); } + @Test + public void testCatchAsync() throws Exception { + SettableApiFuture future = SettableApiFuture.create(); + ApiFuture fallback = + ApiFutures.catchingAsync( + future, + Exception.class, + new ApiAsyncFunction() { + @Override + public ApiFuture apply(Exception ex) { + return ApiFutures.immediateFuture(42); + } + }, + directExecutor()); + future.setException(new Exception()); + assertThat(fallback.get()).isEqualTo(42); + } + @Test public void testTransform() throws Exception { SettableApiFuture inputFuture = SettableApiFuture.create(); diff --git a/version.txt b/version.txt index a8fdfda1c..f8e233b27 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.8.1 +1.9.0