diff --git a/.github/release-please.yml b/.github/release-please.yml new file mode 100644 index 000000000..ecee50f16 --- /dev/null +++ b/.github/release-please.yml @@ -0,0 +1,25 @@ +releaseType: java-yoshi +bumpMinorPreMajor: true +handleGHRelease: true +branches: + - releaseType: java-lts + bumpMinorPreMajor: true + branch: 1.10.1-sp + handleGHRelease: true + - bumpMinorPreMajor: true + handleGHRelease: true + releaseType: java-yoshi + branch: java7 + - releaseType: java-backport + bumpMinorPreMajor: true + handleGHRelease: true + branch: 2.0.x + - releaseType: java-backport + bumpMinorPreMajor: true + handleGHRelease: true + branch: 2.1.x + - releaseType: java-backport + bumpMinorPreMajor: true + handleGHRelease: true + branch: 2.2.x + diff --git a/.github/release-trigger.yml b/.github/release-trigger.yml new file mode 100644 index 000000000..1d1a3361c --- /dev/null +++ b/.github/release-trigger.yml @@ -0,0 +1,2 @@ +enabled: true +multiScmName: api-common-java diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1204a607d..000000000 --- a/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# Build results -bin -build -.gradle -tmp_gh-pages - -# Eclipse -.apt_generated -.classpath -.factorypath -.project -.settings - -# Intellij -.idea -*.iml -*.iws -*.ipr diff --git a/.kokoro/build.sh b/.kokoro/build.sh deleted file mode 100755 index dad012856..000000000 --- a/.kokoro/build.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/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 deleted file mode 100644 index f10834a28..000000000 --- a/.kokoro/common.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# 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 deleted file mode 100644 index 1c23fa586..000000000 --- a/.kokoro/continuous/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# 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 deleted file mode 100644 index 709f2b4c7..000000000 --- a/.kokoro/continuous/java11.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index cb24f44ee..000000000 --- a/.kokoro/continuous/java7.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index 3b017fc80..000000000 --- a/.kokoro/continuous/java8.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index 1c23fa586..000000000 --- a/.kokoro/presubmit/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# 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 deleted file mode 100644 index 709f2b4c7..000000000 --- a/.kokoro/presubmit/java11.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index cb24f44ee..000000000 --- a/.kokoro/presubmit/java7.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index 3b017fc80..000000000 --- a/.kokoro/presubmit/java8.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index c22ce6933..000000000 --- a/.kokoro/release/common.cfg +++ /dev/null @@ -1,49 +0,0 @@ -# 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 deleted file mode 100755 index d5738d430..000000000 --- a/.kokoro/release/common.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/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 deleted file mode 100644 index feb878972..000000000 --- a/.kokoro/release/drop.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# 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 deleted file mode 100755 index ce6ae7543..000000000 --- a/.kokoro/release/drop.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/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 deleted file mode 100644 index d69f1d6f2..000000000 --- a/.kokoro/release/promote.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# 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 deleted file mode 100755 index 2dcfd256d..000000000 --- a/.kokoro/release/promote.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/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 deleted file mode 100644 index 043f92f13..000000000 --- a/.kokoro/release/publish_javadoc.cfg +++ /dev/null @@ -1,19 +0,0 @@ -# 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 deleted file mode 100755 index 09e830704..000000000 --- a/.kokoro/release/publish_javadoc.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/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 deleted file mode 100644 index 4016988c9..000000000 --- a/.kokoro/release/stage.cfg +++ /dev/null @@ -1,35 +0,0 @@ -# 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 deleted file mode 100755 index f927ce143..000000000 --- a/.kokoro/release/stage.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/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 deleted file mode 100755 index 3e90f6494..000000000 --- a/.kokoro/trampoline.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/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 deleted file mode 100644 index 2e07a726e..000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -sudo: false -dist: trusty -language: java -addons: - # https://github.com/travis-ci/travis-ci/issues/5227#issuecomment-165131913 - hosts: - - fake-hostname-to-work-around-travis-bug - hostname: fake-hostname-to-work-around-travis-bug -jdk: - - oraclejdk8 - - openjdk8 -script: - ./gradlew check --info -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 46b2a08ea..2add2547a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,43 +1,94 @@ -# Contributor Code of Conduct + +# Code of Conduct -As contributors and maintainers of this project, -and in the interest of fostering an open and welcoming community, -we pledge to respect all people who contribute through reporting issues, -posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. +## Our Pledge -We are committed to making participation in this project -a harassment-free experience for everyone, -regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, -such as physical or electronic -addresses, without explicit permission -* Other unethical or unprofessional conduct. +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. -By adopting this Code of Conduct, -project maintainers commit themselves to fairly and consistently -applying these principles to every aspect of managing this project. -Project maintainers who do not follow or enforce the Code of Conduct -may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue -or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, -available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +This Code of Conduct also applies outside the project spaces when the Project +Steward has a reasonable belief that an individual's behavior may have a +negative impact on the project or its community. + +## Conflict Resolution + +We do not believe that all conflict is bad; healthy debate and disagreement +often yield positive results. However, it is never okay to be disrespectful or +to engage in behavior that violates the project’s code of conduct. + +If you see someone violating the code of conduct, you are encouraged to address +the behavior directly with those involved. Many issues can be resolved quickly +and easily, and this gives people more control over the outcome of their +dispute. If you are unable to resolve the matter for any reason, or if the +behavior is threatening or harassing, report it. We are dedicated to providing +an environment where participants feel welcome and safe. + +Reports should be directed to *googleapis-stewards@google.com*, the +Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to +receive and address reported violations of the code of conduct. They will then +work with a committee consisting of representatives from the Open Source +Programs Office and the Google Open Source Strategy team. If for any reason you +are uncomfortable reaching out to the Project Steward, please email +opensource@google.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is taken. +The identity of the reporter will be omitted from the details of the report +supplied to the accused. In potentially harmful situations, such as ongoing +harassment or threats to anyone's safety, we may take action without notice. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html \ No newline at end of file diff --git a/LICENSE b/LICENSE index 6d16b6578..b442fc4b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,4 @@ Copyright 2016, Google Inc. -All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -24,4 +23,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 0ef1b58a3..0f12dc1a8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ API Common for Java ============================== -[![Build Status](https://travis-ci.org/googleapis/api-common-java.svg?branch=master)](https://travis-ci.org/googleapis/api-common-java) +[![Build Status](https://travis-ci.org/googleapis/api-common-java.svg?branch=main)](https://travis-ci.org/googleapis/api-common-java) -[![Code Coverage](https://img.shields.io/codecov/c/github/googleapis/api-common-java.svg)](https://codecov.io/github/googleapis/api-common-java) +🚌 In January 2023, this library has moved to [gapic-generator-java/api-common-java](https://github.com/googleapis/gapic-generator-java/tree/main/api-common-java). This repository will be archived in the future. Future releases will appear in the new repository (https://github.com/googleapis/gapic-generator-java/releases). +The Maven artifact coordinates (com.google.api:api-common) remain the same. -- [Documentation](http://googleapis.github.io/api-common-java/apidocs) +- [Documentation](https://googleapis.dev/java/api-common/latest/index.html) API Common for Java is a library for foundational types relating to Google APIs. It currently contains the following packages: @@ -15,10 +16,23 @@ APIs. It currently contains the following packages: formatted as Google API resource names. - resourcenames: Resource Name library used by generated resource name types +> For new and existing Developers/ Contributors: +> +> In December 2022, api-common-java's build tool has been migrated from gradle to maven. +> Gradle related files are no longer being maintained and will be removed. +> +> The artifact coordinates in Maven Central (`{{ group_id }}:{{ artifact_id }}`) remain the same. + + Java Versions ------------- -Java 7 or above is required for using this library. +Java 8 or above is required for using this library. + +To build this project, JDK 11 or above is required. +The build produces Java bytecode targeted for Java 8. + +The project uses Maven to build. Contributing ------------ @@ -52,8 +66,23 @@ and probably not then. License ------- -BSD - See [LICENSE] for more information. +BSD 3-Clause - See [LICENSE] for more information. + +Build and Test +-------------- +To build this library, please do the following. + +```sh +mvn clean install +``` + +After making changes, run the following commands to format your code and test your changes. + +```sh +mvn fmt:format +mvn test +``` -[CONTRIBUTING]:https://github.com/googleapis/path-template-java/blob/master/CONTRIBUTING.md -[LICENSE]: https://github.com/googleapis/path-template-java/blob/master/LICENSE +[CONTRIBUTING]:https://github.com/googleapis/api-common-java/blob/main/CONTRIBUTING.md +[LICENSE]: https://github.com/googleapis/api-common-java/blob/main/LICENSE diff --git a/RELEASING.md b/RELEASING.md deleted file mode 100644 index 9f8e308bb..000000000 --- a/RELEASING.md +++ /dev/null @@ -1,79 +0,0 @@ -One-time setup -============== - -Set up Sonatype Account ------------------------ -* Sign up for a Sonatype JIRA account [here](https://issues.sonatype.org) -* Click *Sign Up* in the login box, follow instructions - -Get access to repository ------------------------- -* Go to [community support](https://issues.sonatype.org/browse/OSSRH) -* Ask for publish rights by creating an issue similar to [this one](https://issues.sonatype.org/browse/OSSRH-32031) - * You must be logged in to create a new issue - * Use the *Create* button at the top tab - -* Generate the key `gpg --gen-key` - * Keep the defaults, but specify a passphrase - -* Determine your `gpg` version: `gpg -- version` - -* Find the ID of your public key - * If you're using GPG version 1.y.z, `gpg --list-secret-keys` - * Look for the line with format `sec 2048R/ABCDEFGH 2015-11-17` - * The `ABCDEFGH` is the ID for your public key - * If you're using GPG version 2.y.z `gpg --list-secret-keys --keyid-format LONG` - * Look for line with format `sec rsa2048/ABCDEFGHIJKLMNOP` - * The `ABCDEFGHIJKLMNOP` is the ID. It is 16-byte long, but Gradle - only support 8-byte keys. Use the *last* 8 bytes of the key when - following the rest of this document. - * `gpg --export-secret-keys $HOME/.gnupg/secring.gpg` - -* Upload your public key to a public server: `gpg --send-keys --keyserver hkp://pgp.mit.edu ` - -Add deploy credential settings ------------------------- -* Create a settings file at `$HOME/.gradle/gradle.properties` with your key information and your sonatype username/password - -``` -signing.keyId= -signing.password= -signing.secretKeyRingFile=/usr/local/google/home//.gnupg/secring.gpg - -ossrhUsername= -ossrhPassword= -``` - -To prepare a release -==================== - -Update version and deploy to Sonatype -------------------------------------- -1. Update `version.txt` to the release version you want -2. Run `./gradlew stageRelease` to: - * Regenerate `gh-pages` branch containing Javadocs - * Stage artifacts on Sonatype: to the staging repository if "-SNAPSHOT" is *not* included in the version; otherwise to the snapshot repository only -3. Submit a pull request, get it reviewed, and submit - -Publish the release -------------------- -1. Run `./gradlew finalizeRelease` - * Note: this will release **ALL** versions that have been staged to Sonatype: - if you have staged versions you do not intend to release, remove these first - from the [Nexus Repository Manager](https://oss.sonatype.org/) by logging in - (upper right) and browsing staging repositories (left panel) -2. It will take some time (~10 min to ~8 hours) for the package to transition -3. Publish a new release on Github: - * Go to the [releases page](https://github.com/googleapis/api-common-java/releases) and click "Draft a new release" - in order to start a new draft. - * Make sure the "Tag Version" is `vX.Y.Z` and the "Release Title" is `X.Y.Z`, where `X.Y.Z` is the release - version as listed in the `version.txt` files. - * Add the commits since the last release into the release draft. Try to group them into sections with related - changes. Anything that is a breaking change needs to be marked with `*breaking change*`. Such changes are - only allowed for alpha/beta modules and `@BetaApi` features. - * Ensure that the format is consistent with previous releases. After adding any missing updates and - reformatting as necessary, publish the draft. - -Bump development version ------------------------- -1. Update `version.txt` to the following "-SNAPSHOT" version diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..8b58ae9c0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). + +The Google Security Team will respond within 5 working days of your report on g.co/vulnz. + +We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 859349425..000000000 --- a/build.gradle +++ /dev/null @@ -1,377 +0,0 @@ -import groovy.io.FileType - -buildscript { - repositories { - mavenLocal() - maven { - url 'https://plugins.gradle.org/m2/' - } - mavenCentral() - jcenter() - } - dependencies { - 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" - } -} - -apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'eclipse' -apply plugin: 'idea' -apply plugin: 'jacoco' -apply plugin: 'signing' -apply plugin: 'com.github.sherter.google-java-format' -apply plugin: 'io.codearte.nexus-staging' - -group = "com.google.api" -archivesBaseName = "api-common" - -project.version = new File("version.txt").text.trim() - -sourceCompatibility = 1.7 -targetCompatibility = 1.7 - -// Dependencies -// ------------ - -ext { - // Shortcuts for libraries we are using - libraries = [ - javax_annotations: 'javax.annotation:javax.annotation-api:1.3.2', - auto_value_annotations: 'com.google.auto.value:auto-value-annotations:1.7.2', - auto_value: 'com.google.auto.value:auto-value:1.7.2', - guava: 'com.google.guava:guava:29.0-android', - jsr305: 'com.google.code.findbugs:jsr305:3.0.2', - error_prone_annotations: 'com.google.errorprone:error_prone_annotations:2.3.4', - - // Testing - junit: 'junit:junit:4.13', - mockito: 'org.mockito:mockito-core:1.10.19', - truth: 'com.google.truth:truth:1.0.1', - ] -} - -repositories { - mavenLocal() - mavenCentral() -} - -dependencies { - - annotationProcessor libraries.auto_value - - compile libraries.guava, - libraries.jsr305, - libraries.javax_annotations, - libraries.auto_value_annotations - - compileOnly libraries.error_prone_annotations - - testCompile libraries.junit, - libraries.mockito, - libraries.truth -} - -clean.doFirst { - delete 'tmp_gh-pages/' -} - -jacocoTestReport { - reports { - xml.enabled true - html.enabled true - } -} - -check.dependsOn jacocoTestReport - -// jar with automatic module name: -jar { - manifest { - attributes('Automatic-Module-Name': 'com.google.api.apicommon') - } -} - -// Source jar -// ---------- - -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} - -// JavaDoc -// ------- - -task javadocJar(type: Jar) { - classifier = 'javadoc' - from javadoc -} - -javadoc.options { - encoding = 'UTF-8' - links 'https://docs.oracle.com/javase/7/docs/api/' -} - -// Test Logging -// ------------ - -test { - testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - exceptionFormat = 'full' - } -} - - -// Eclipse Annotation Processing -// ----------------------------- - -ext { - eclipseAptFolder = '.apt_generated' - eclipseSettingsDir = file('.settings') -} - -configurations { - codeGeneration -} - -dependencies { - codeGeneration libraries.auto_value, libraries.jsr305 - compile libraries.jsr305, libraries.auto_value_annotations -} - -compileJava.classpath += configurations.codeGeneration - -eclipse { - jdt.file.withProperties { - it['org.eclipse.jdt.core.compiler.processAnnotations'] = 'enabled' - } -} - -tasks.eclipseJdt { - doFirst { - def aptPrefs = - file("${eclipseSettingsDir}/org.eclipse.jdt.apt.core.prefs") - aptPrefs.parentFile.mkdirs() - - aptPrefs.text = """\ - eclipse.preferences.version=1 - org.eclipse.jdt.apt.aptEnabled=true - org.eclipse.jdt.apt.genSrcDir=${eclipseAptFolder} - org.eclipse.jdt.apt.reconcileEnabled=true - """.stripIndent() - - file('.factorypath').withWriter { - new groovy.xml.MarkupBuilder(it).'factorypath' { - project.configurations.codeGeneration.each { dep-> - factorypathentry( - kind:'EXTJAR', - id:dep.absolutePath, - enabled:true, - runInBatchMode:false) - } - } - } - } -} - -tasks.cleanEclipseJdt { - doFirst { - delete file("${eclipseSettingsDir}/org.eclipse.jdt.apt.core.prefs"), - file('.factorypath') - } -} - -// Publishing -// ---------- - -artifacts { - archives javadocJar, sourcesJar -} - -signing { - required { gradle.taskGraph.hasTask("uploadArchives") } - if (project.hasProperty('signing.gnupg.executable')) { - useGpgCmd() - } - sign configurations.archives -} - -if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) { - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - pom.project { - name 'API Common' - packaging 'jar' - artifactId 'api-common' - description 'Common utilities for Google APIs in Java' - url 'https://github.com/googleapis/api-common-java' - - scm { - url 'https://github.com/googleapis/api-common-java' - connection 'scm:git:https://github.com/googleapis/api-common-java.git' - } - - licenses { - license { - name 'BSD' - url 'https://github.com/googleapis/api-common-java/blob/master/LICENSE' - } - } - - developers { - developer { - id 'GoogleAPIs' - name 'GoogleAPIs' - email 'googleapis@googlegroups.com' - url 'https://github.com/googleapis' - organization = 'Google, Inc.' - organizationUrl 'https://www.google.com' - } - } - } - } - } - } -} - -gradle.projectsEvaluated { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" - } -} - -// Formatting tasks -// ================ - -task verifyLicense { - doLast { - def licenseText = new File(rootProject.rootDir, 'license-header-javadoc.txt').text - def srcFiles = [] - sourceSets - .collectMany{it.allJava.getSrcDirs()} - .each{it.eachFileRecurse(FileType.FILES, {srcFiles << new Tuple(it, it.text)})} - srcFiles = srcFiles - .findAll{it.get(0).path.endsWith(".java")} - .collect{new Tuple(it.get(0), it.get(1).replaceAll("Copyright 20[0-9]{2}", "Copyright 20xx"))} - .findAll{!it.get(1).startsWith(licenseText)} - if (srcFiles.asList().size() > 0) { - srcFiles.each({println 'missing license: ' + it.get(0)}) - throw new IllegalStateException("Above files do not have licenses") - } - } -} -test.dependsOn verifyLicense - -googleJavaFormat { - toolVersion '1.0' -} -tasks.googleJavaFormat { - exclude '.apt_generated/**' - exclude 'bin/**' - exclude 'build/**' -} -tasks.verifyGoogleJavaFormat { - exclude '.apt_generated/**' - exclude 'bin/**' - exclude 'build/**' -} -test.dependsOn verifyGoogleJavaFormat - -// Release -// ======= - -task checkOutGhPages { - doLast { - if (!new File('tmp_gh-pages').exists()) { - exec { - commandLine 'git', 'clone', '--branch', 'gh-pages', - '--single-branch', 'https://github.com/googleapis/api-common-java/', 'tmp_gh-pages' - } - } - } -} - -task copyFilesToGhPages { - dependsOn 'checkOutGhPages' - dependsOn 'javadoc' - doLast { - def newSiteDirPath = 'tmp_gh-pages/' + project.version + '/apidocs/' - new File(newSiteDirPath).mkdirs() - copy { - from 'build/docs/javadoc' - into newSiteDirPath - } - copy { - from 'README.md' - into 'tmp_gh-pages' - rename { filename -> filename.replace 'README', 'index' } - } - } -} - -task createApiDocsRedirect { - dependsOn 'copyFilesToGhPages' - doLast { - def template = new File('templates/apidocs_index.html.template').text - def outputContent = template.replace('{{siteVersion}}', project.version) - new File('tmp_gh-pages/apidocs/index.html').write(outputContent) - } -} - -task publishDocs { - dependsOn 'closeAndReleaseRepository' - doLast { - exec { - workingDir './tmp_gh-pages' - commandLine 'git', 'add', '.' - } - exec { - workingDir './tmp_gh-pages' - commandLine 'git', 'commit', '-m', 'Release docs for ' + project.version - } - exec { - workingDir './tmp_gh-pages' - commandLine 'git', 'push' - } - } -} - -// 1. Regenerates the gh-pages branch under tmp_gh-pages -// 2. Stages the artifact on Sonatype -task stageRelease { - dependsOn 'createApiDocsRedirect' - doLast { - exec { - // We need to spawn a new gradle build process in order to upload appropriately - // More details: http://stackoverflow.com/questions/31614735/gradle-uploadarchives-artificats-namespace-when-depending-on-a-plugin - commandLine './gradlew', 'uploadArchives' - } - } -} - -// 1. Closes and releases the artifact on Sonatype -// 2. Commits and pushes the new docs -// 3. Removes tmp_gh-pages -// Note: This task assumes that the 'stageRelease' task has been completed. -task finalizeRelease { - dependsOn 'publishDocs' - doLast { - exec { - commandLine 'rm', '-r', 'tmp_gh-pages' - } - } -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index a34ba8bb8..000000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index f6fd8db47..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Sep 20 10:02:51 PDT 2016 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip diff --git a/gradlew b/gradlew deleted file mode 100755 index 91a7e269e..000000000 --- a/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index aec99730b..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/license-header-javadoc.txt b/license-header-javadoc.txt deleted file mode 100644 index beea26020..000000000 --- a/license-header-javadoc.txt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 20xx, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/renovate.json b/renovate.json deleted file mode 100644 index b76243f10..000000000 --- a/renovate.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": [ - ":separateMajorReleases", - ":combinePatchMinorReleases", - ":ignoreUnstable", - ":prImmediately", - ":updateNotScheduled", - ":automergeDisabled", - ":ignoreModulesAndTests", - ":maintainLockFilesDisabled", - ":autodetectPinVersions" - ], - "packageRules": [ - { - "packagePatterns": [ - "^com.google.guava:" - ], - "versionScheme": "docker" - } - ] -} diff --git a/src/main/java/com/google/api/core/AbstractApiFuture.java b/src/main/java/com/google/api/core/AbstractApiFuture.java deleted file mode 100644 index 0299c9277..000000000 --- a/src/main/java/com/google/api/core/AbstractApiFuture.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.util.concurrent.AbstractFuture; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import javax.annotation.Nullable; - -/** - * Abstract implementation of ApiFuture that mirrors {@code AbstractFuture} in Guava. - */ -public abstract class AbstractApiFuture implements ApiFuture { - private final InternalSettableFuture impl = new InternalSettableFuture(); - - public void addListener(Runnable listener, Executor executor) { - impl.addListener(listener, executor); - } - - public boolean cancel(boolean mayInterruptIfRunning) { - return impl.cancel(mayInterruptIfRunning); - } - - public V get() throws InterruptedException, ExecutionException { - return impl.get(); - } - - public V get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return impl.get(timeout, unit); - } - - public boolean isCancelled() { - return impl.isCancelled(); - } - - public boolean isDone() { - return impl.isDone(); - } - - protected boolean set(V value) { - return impl.set(value); - } - - protected boolean setException(Throwable throwable) { - return impl.setException(throwable); - } - - protected void interruptTask() {} - - /* package-private for internal library use, to reduce call layering */ - ListenableFuture getInternalListenableFuture() { - return impl; - } - - private class InternalSettableFuture extends AbstractFuture { - @Override - protected boolean set(@Nullable V value) { - return super.set(value); - } - - @Override - protected boolean setException(Throwable throwable) { - return super.setException(throwable); - } - - protected void interruptTask() { - AbstractApiFuture.this.interruptTask(); - } - } -} diff --git a/src/main/java/com/google/api/core/AbstractApiService.java b/src/main/java/com/google/api/core/AbstractApiService.java deleted file mode 100644 index d32f1e410..000000000 --- a/src/main/java/com/google/api/core/AbstractApiService.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.collect.ImmutableMap; -import com.google.common.util.concurrent.AbstractService; -import com.google.common.util.concurrent.Service; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Base class for {@link ApiService}. Similar to Guava's {@code AbstractService} but redeclared to - * that Guava can be shaded. - */ -public abstract class AbstractApiService implements ApiService { - private static final ImmutableMap guavaToGaxState = - ImmutableMap.builder() - .put(Service.State.FAILED, ApiService.State.FAILED) - .put(Service.State.NEW, ApiService.State.NEW) - .put(Service.State.RUNNING, ApiService.State.RUNNING) - .put(Service.State.STARTING, ApiService.State.STARTING) - .put(Service.State.STOPPING, ApiService.State.STOPPING) - .put(Service.State.TERMINATED, ApiService.State.TERMINATED) - .build(); - - private final InnerService impl = new InnerService(); - - protected AbstractApiService() {} - - protected abstract void doStart(); - - protected abstract void doStop(); - - @Override - public void addListener(final ApiService.Listener listener, Executor executor) { - impl.addListener( - new Service.Listener() { - @Override - public void failed(Service.State from, Throwable failure) { - listener.failed(guavaToGaxState.get(from), failure); - } - - @Override - public void running() { - listener.running(); - } - - @Override - public void starting() { - listener.starting(); - } - - @Override - public void stopping(Service.State from) { - listener.stopping(guavaToGaxState.get(from)); - } - - @Override - public void terminated(Service.State from) { - listener.terminated(guavaToGaxState.get(from)); - } - }, - executor); - } - - public void awaitRunning() { - impl.awaitRunning(); - } - - public void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { - impl.awaitRunning(timeout, unit); - } - - public void awaitTerminated() { - impl.awaitTerminated(); - } - - public void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { - impl.awaitTerminated(timeout, unit); - } - - public Throwable failureCause() { - return impl.failureCause(); - } - - public boolean isRunning() { - return impl.isRunning(); - } - - public ApiService startAsync() { - impl.startAsync(); - return this; - } - - public State state() { - return guavaToGaxState.get(impl.state()); - } - - public ApiService stopAsync() { - impl.stopAsync(); - return this; - } - - protected void notifyStarted() { - impl.innerNotifyStarted(); - } - - protected void notifyStopped() { - impl.innerNotifyStopped(); - } - - protected void notifyFailed(Throwable cause) { - impl.innerNotifyFailed(cause); - } - - private class InnerService extends AbstractService { - @Override - protected void doStart() { - AbstractApiService.this.doStart(); - } - - @Override - protected void doStop() { - AbstractApiService.this.doStop(); - } - - private void innerNotifyStarted() { - notifyStarted(); - } - - private void innerNotifyStopped() { - notifyStopped(); - } - - private void innerNotifyFailed(Throwable cause) { - notifyFailed(cause); - } - } -} diff --git a/src/main/java/com/google/api/core/ApiAsyncFunction.java b/src/main/java/com/google/api/core/ApiAsyncFunction.java deleted file mode 100644 index 1de164ceb..000000000 --- a/src/main/java/com/google/api/core/ApiAsyncFunction.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -/** - * Transforms a value, possibly asynchronously. - * - *

- * It is similar to Guava's {@code AsyncFunction}, redeclared so that Guava can be shaded. - */ -public interface ApiAsyncFunction { - /** - * Returns an output Future to use in place of the given input. The output Future need not be - * done, making AsyncFunction suitable for asynchronous derivations. - * - *

- * Throwing an exception from this method is equivalent to returning a failing Future. - */ - ApiFuture apply(I input) throws Exception; -} diff --git a/src/main/java/com/google/api/core/ApiClock.java b/src/main/java/com/google/api/core/ApiClock.java deleted file mode 100644 index 71053e66d..000000000 --- a/src/main/java/com/google/api/core/ApiClock.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -/** - * An interface for getting the current value of a high-resolution time source, in nanoseconds. - * - * Clocks other than {@link NanoClock} are typically used only for testing. - * - * This interface is required in addition to Java 8's Clock, because nanoTime is required to compare - * values with io.grpc.CallOptions.getDeadlineNanoTime(). - */ -public interface ApiClock { - - /** - * Returns the current value of this clock's high-resolution time source, in nanoseconds. - */ - long nanoTime(); - - /** - * Returns the current value of this clock's high-resolution time source, in milliseconds. - */ - long millisTime(); -} diff --git a/src/main/java/com/google/api/core/ApiFunction.java b/src/main/java/com/google/api/core/ApiFunction.java deleted file mode 100644 index b814a8e5f..000000000 --- a/src/main/java/com/google/api/core/ApiFunction.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -/** - * Legacy version of Function. - * - *

- * It is similar to Guava's {@code Function}, redeclared so that Guava can be shaded. - */ -public interface ApiFunction { - T apply(F input); -} diff --git a/src/main/java/com/google/api/core/ApiFuture.java b/src/main/java/com/google/api/core/ApiFuture.java deleted file mode 100644 index 6a5bbf6af..000000000 --- a/src/main/java/com/google/api/core/ApiFuture.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.util.concurrent.Executor; -import java.util.concurrent.Future; - -/** - * A Future that can have a listener added. - * - * Similar to Guava's {@code ListenableFuture}, but redeclared so that Guava could be shaded. - */ -public interface ApiFuture extends Future { - void addListener(Runnable listener, Executor executor); -} diff --git a/src/main/java/com/google/api/core/ApiFutureCallback.java b/src/main/java/com/google/api/core/ApiFutureCallback.java deleted file mode 100644 index 9457d60a7..000000000 --- a/src/main/java/com/google/api/core/ApiFutureCallback.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -/** - * A callback for accepting the results of an {@link ApiFuture}. - * - *

- * It is similar to Guava's {@code FutureCallback}, redeclared so that Guava can be shaded. - */ -public interface ApiFutureCallback { - void onFailure(Throwable t); - - void onSuccess(V result); -} diff --git a/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java b/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java deleted file mode 100644 index fc8745231..000000000 --- a/src/main/java/com/google/api/core/ApiFutureToListenableFuture.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.util.concurrent.ListenableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * INTERNAL USE ONLY. Adapter from GAX ApiFuture to Guava ListenableFuture. - */ -@InternalApi -public class ApiFutureToListenableFuture implements ListenableFuture { - private final ApiFuture apiFuture; - - public ApiFutureToListenableFuture(ApiFuture apiFuture) { - this.apiFuture = apiFuture; - } - - @Override - public void addListener(Runnable listener, Executor executor) { - apiFuture.addListener(listener, executor); - } - - @Override - public boolean cancel(boolean b) { - return apiFuture.cancel(b); - } - - @Override - public boolean isCancelled() { - return apiFuture.isCancelled(); - } - - @Override - public boolean isDone() { - return apiFuture.isDone(); - } - - @Override - public V get() throws InterruptedException, ExecutionException { - return apiFuture.get(); - } - - @Override - public V get(long l, TimeUnit timeUnit) - throws InterruptedException, ExecutionException, TimeoutException { - return apiFuture.get(l, timeUnit); - } -} diff --git a/src/main/java/com/google/api/core/ApiFutures.java b/src/main/java/com/google/api/core/ApiFutures.java deleted file mode 100644 index d02892619..000000000 --- a/src/main/java/com/google/api/core/ApiFutures.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import com.google.common.util.concurrent.AsyncFunction; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import java.util.List; -import java.util.concurrent.Executor; -import javax.annotation.Nullable; - -/** Static utility methods for the {@link ApiFuture} interface. */ -public final class ApiFutures { - private ApiFutures() {} - - /* - * @deprecated Use {@linkplain #addCallback(ApiFuture, ApiFutureCallback, Executor) the - * overload that requires an executor}. For identical behavior, pass {@link - * com.google.common.util.concurrent.MoreExecutors#directExecutor}, but consider whether - * another executor would be safer. - */ - @Deprecated - public static void addCallback( - final ApiFuture future, final ApiFutureCallback callback) { - addCallback(future, callback, directExecutor()); - } - - public static void addCallback( - final ApiFuture future, final ApiFutureCallback callback, Executor executor) { - Futures.addCallback( - listenableFutureForApiFuture(future), - new FutureCallback() { - @Override - public void onFailure(Throwable t) { - callback.onFailure(t); - } - - @Override - public void onSuccess(V v) { - callback.onSuccess(v); - } - }, - executor); - } - - /* - * @deprecated Use {@linkplain #catching(ApiFuture, Class, ApiFunction, Executor) the - * overload that requires an executor}. For identical behavior, pass {@link - * com.google.common.util.concurrent.MoreExecutors#directExecutor}, but consider whether - * another executor would be safer. - */ - @Deprecated - public static ApiFuture catching( - ApiFuture input, - Class exceptionType, - ApiFunction callback) { - return catching(input, exceptionType, callback, directExecutor()); - } - - public static ApiFuture catching( - ApiFuture input, - Class exceptionType, - ApiFunction callback, - Executor executor) { - ListenableFuture catchingFuture = - Futures.catching( - listenableFutureForApiFuture(input), - exceptionType, - new GaxFunctionToGuavaFunction(callback), - executor); - 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)); - } - - public static ApiFuture immediateFailedFuture(Throwable throwable) { - return new ListenableFutureToApiFuture(Futures.immediateFailedFuture(throwable)); - } - - public static ApiFuture immediateCancelledFuture() { - return new ListenableFutureToApiFuture(Futures.immediateCancelledFuture()); - } - - /* - * @deprecated Use {@linkplain #transform(ApiFuture, ApiFunction, Executor) the - * overload that requires an executor}. For identical behavior, pass {@link - * com.google.common.util.concurrent.MoreExecutors#directExecutor}, but consider whether - * another executor would be safer. - */ - @Deprecated - public static ApiFuture transform( - ApiFuture input, final ApiFunction function) { - return transform(input, function, directExecutor()); - } - - public static ApiFuture transform( - ApiFuture input, - final ApiFunction function, - Executor executor) { - return new ListenableFutureToApiFuture<>( - Futures.transform( - listenableFutureForApiFuture(input), - new GaxFunctionToGuavaFunction(function), - executor)); - } - - public static ApiFuture> allAsList( - Iterable> futures) { - return new ListenableFutureToApiFuture<>( - Futures.allAsList( - Iterables.transform( - futures, - new Function, ListenableFuture>() { - public ListenableFuture apply(ApiFuture apiFuture) { - return listenableFutureForApiFuture(apiFuture); - } - }))); - } - /* - * @deprecated Use {@linkplain #transformAsync(ApiFuture, ApiFunction, Executor) the - * overload that requires an executor}. For identical behavior, pass {@link - * com.google.common.util.concurrent.MoreExecutors#directExecutor}, but consider whether - * another executor would be safer. - */ - @Deprecated - public static ApiFuture transformAsync( - ApiFuture input, final ApiAsyncFunction function) { - return transformAsync(input, function, directExecutor()); - } - - public static ApiFuture transformAsync( - ApiFuture input, final ApiAsyncFunction function, Executor executor) { - ListenableFuture listenableInput = listenableFutureForApiFuture(input); - ListenableFuture listenableOutput = - Futures.transformAsync( - listenableInput, - new AsyncFunction() { - @Override - public ListenableFuture apply(I input) throws Exception { - return listenableFutureForApiFuture(function.apply(input)); - } - }, - executor); - return new ListenableFutureToApiFuture<>(listenableOutput); - } - - private static ListenableFuture listenableFutureForApiFuture(ApiFuture apiFuture) { - ListenableFuture listenableFuture; - if (apiFuture instanceof AbstractApiFuture) { - // prefer to use the wrapped ListenableFuture to reduce the number of layers - listenableFuture = ((AbstractApiFuture) apiFuture).getInternalListenableFuture(); - } else { - listenableFuture = new ApiFutureToListenableFuture(apiFuture); - } - return listenableFuture; - } - - private static class GaxFunctionToGuavaFunction - implements com.google.common.base.Function { - private ApiFunction f; - - public GaxFunctionToGuavaFunction(ApiFunction f) { - this.f = f; - } - - @Nullable - @Override - public V apply(@Nullable X input) { - return f.apply(input); - } - } -} diff --git a/src/main/java/com/google/api/core/ApiService.java b/src/main/java/com/google/api/core/ApiService.java deleted file mode 100644 index c843a7daf..000000000 --- a/src/main/java/com/google/api/core/ApiService.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * An object with an operational state, plus asynchronous {@link #startAsync()} and - * {@link #stopAsync()} lifecycle methods to transition between states. Example services include - * webservers, RPC servers and timers. - * - *

- * The normal lifecycle of a service is: - * - *

    - *
  • {@linkplain State#NEW NEW} -> - *
  • {@linkplain State#STARTING STARTING} -> - *
  • {@linkplain State#RUNNING RUNNING} -> - *
  • {@linkplain State#STOPPING STOPPING} -> - *
  • {@linkplain State#TERMINATED TERMINATED} - *
- * - *

- * There are deviations from this if there are failures or if {@link ApiService#stopAsync} is called - * before the {@link ApiService} reaches the {@linkplain State#RUNNING RUNNING} state. The set of - * legal transitions form a DAG, - * therefore every method of the listener will be called at most once. N.B. The {@link State#FAILED} - * and {@link State#TERMINATED} states are terminal states, once a service enters either of these - * states it cannot ever leave them. - * - *

- * Implementors of this interface are strongly encouraged to extend {@link AbstractApiService} which - * implement this interface and make the threading and state management easier. - * - *

- * Similar to Guava's {@code Service}, but redeclared so that Guava could be shaded. - */ -public interface ApiService { - /** - * Registers a {@link Listener} to be {@linkplain Executor#execute executed} on the given - * executor. The listener will have the corresponding transition method called whenever the - * service changes state. The listener will not have previous state changes replayed, so it is - * suggested that listeners are added before the service starts. - * - *

- * {@code addListener} guarantees execution ordering across calls to a given listener but not - * across calls to multiple listeners. Specifically, a given listener will have its callbacks - * invoked in the same order as the underlying service enters those states. Additionally, at most - * one of the listener's callbacks will execute at once. However, multiple listeners' callbacks - * may execute concurrently, and listeners may execute in an order different from the one in which - * they were registered. - * - *

- * RuntimeExceptions thrown by a listener will be caught and logged. Any exception thrown during - * {@code Executor.execute} (e.g., a {@code RejectedExecutionException}) will be caught and - * logged. - * - * @param listener the listener to run when the service changes state is complete - * @param executor the executor in which the listeners callback methods will be run. - */ - void addListener(Listener listener, Executor executor); - - /** - * Waits for the {@link ApiService} to reach the {@linkplain State#RUNNING running state}. - * - * @throws IllegalStateException if the service reaches a state from which it is not possible to - * enter the {@link State#RUNNING} state. e.g. if the {@code state} is {@code State#TERMINATED} - * when this method is called then this will throw an IllegalStateException. - */ - void awaitRunning(); - - /** - * Waits for the {@link ApiService} to reach the {@linkplain State#RUNNING running state} for no - * more than the given time. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @throws TimeoutException if the service has not reached the given state within the deadline - * @throws IllegalStateException if the service reaches a state from which it is not possible to - * enter the {@link State#RUNNING RUNNING} state. e.g. if the {@code state} is - * {@code State#TERMINATED} when this method is called then this will throw an - * IllegalStateException. - */ - void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException; - - /** - * Waits for the {@link ApiService} to reach the {@linkplain State#TERMINATED terminated state}. - * - * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. - */ - void awaitTerminated(); - - /** - * Waits for the {@link ApiService} to reach a terminal state (either {@link State#TERMINATED - * terminated} or {@link State#FAILED failed}) for no more than the given time. - * - * @param timeout the maximum time to wait - * @param unit the time unit of the timeout argument - * @throws TimeoutException if the service has not reached the given state within the deadline - * @throws IllegalStateException if the service {@linkplain State#FAILED fails}. - */ - void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException; - - /** - * Returns the {@link Throwable} that caused this service to fail. - * - * @throws IllegalStateException if this service's state isn't {@linkplain State#FAILED FAILED}. - */ - Throwable failureCause(); - - /** Returns {@code true} if this service is {@linkplain State#RUNNING running}. */ - boolean isRunning(); - - /** - * If the service state is {@link State#NEW}, this initiates service startup and returns - * immediately. A stopped service may not be restarted. - * - * @return this - * @throws IllegalStateException if the service is not {@link State#NEW} - */ - ApiService startAsync(); - - /** Returns the lifecycle state of the service. */ - State state(); - - /** - * If the service is {@linkplain State#STARTING starting} or {@linkplain State#RUNNING running}, - * this initiates service shutdown and returns immediately. If the service is - * {@linkplain State#NEW new}, it is {@linkplain State#TERMINATED terminated} without having been - * started nor stopped. If the service has already been stopped, this method returns immediately - * without taking action. - * - * @return this - */ - ApiService stopAsync(); - - /** - * The lifecycle states of a service. - * - *

- * The ordering of the {@link State} enum is defined such that if there is a state transition from - * {@code A -> B} then {@code A.compareTo(B) < 0}. N.B. The converse is not true, i.e. if - * {@code A.compareTo(B) < 0} then there is not guaranteed to be a valid state transition - * {@code A -> B}. - */ - @BetaApi - enum State { - /** - * A service in this state has encountered a problem and may not be operational. It cannot be - * started nor stopped. - */ - FAILED, - - /** A service in this state is inactive. It does minimal work and consumes minimal resources. */ - NEW, - - /** A service in this state is operational. */ - RUNNING, - - /** A service in this state is transitioning to {@link #RUNNING}. */ - STARTING, - - /** A service in this state is transitioning to {@link #TERMINATED}. */ - STOPPING, - - /** - * A service in this state has completed execution normally. It does minimal work and consumes - * minimal resources. - */ - TERMINATED - } - - /** - * A listener for the various state changes that a {@link ApiService} goes through in its - * lifecycle. - * - *

- * All methods are no-ops by default, implementors should override the ones they care about. - */ - @BetaApi - abstract class Listener { - /** - * Called when the service transitions to the {@linkplain State#FAILED FAILED} state. The - * {@linkplain State#FAILED FAILED} state is a terminal state in the transition diagram. - * Therefore, if this method is called, no other methods will be called on the {@link Listener}. - * - * @param from The previous state that is being transitioned from. Failure can occur in any - * state with the exception of {@linkplain State#NEW NEW} or {@linkplain State#TERMINATED - * TERMINATED}. - * @param failure The exception that caused the failure. - */ - public void failed(State from, Throwable failure) {} - - /** - * Called when the service transitions from {@linkplain State#STARTING STARTING} to - * {@linkplain State#RUNNING RUNNING}. This occurs when a service has successfully started. - */ - public void running() {} - - /** - * Called when the service transitions from {@linkplain State#NEW NEW} to - * {@linkplain State#STARTING STARTING}. This occurs when {@link ApiService#startAsync} is - * called the first time. - */ - public void starting() {} - - /** - * Called when the service transitions to the {@linkplain State#STOPPING STOPPING} state. The - * only valid values for {@code from} are {@linkplain State#STARTING STARTING} or - * {@linkplain State#RUNNING RUNNING}. This occurs when {@link ApiService#stopAsync} is called. - * - * @param from The previous state that is being transitioned from. - */ - public void stopping(State from) {} - - /** - * Called when the service transitions to the {@linkplain State#TERMINATED TERMINATED} state. - * The {@linkplain State#TERMINATED TERMINATED} state is a terminal state in the transition - * diagram. Therefore, if this method is called, no other methods will be called on the - * {@link Listener}. - * - * @param from The previous state that is being transitioned from. The only valid values for - * this are {@linkplain State#NEW NEW}, {@linkplain State#RUNNING RUNNING} or - * {@linkplain State#STOPPING STOPPING}. - */ - public void terminated(State from) {} - } -} diff --git a/src/main/java/com/google/api/core/BetaApi.java b/src/main/java/com/google/api/core/BetaApi.java deleted file mode 100644 index f35cab81b..000000000 --- a/src/main/java/com/google/api/core/BetaApi.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates a public API that can change at any time, and has no guarantee of API stability and - * backward-compatibility. - * - *

- * Usage guidelines: - *

    - *
  1. This annotation is used only on APIs with public visibility. Internal interfaces should not - * use it.
  2. - *
  3. This annotation should only be added to new APIs. Adding it to an existing API is considered - * API-breaking.
  4. - *
  5. Removing this annotation from an API gives it stable status, assuming the API doesn't have - * other annotations denoting instability (such as {@link InternalApi} or - * {@link InternalExtensionOnly}).
  6. - *
- */ -@BetaApi -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE -}) -@Documented -public @interface BetaApi { - /** - * Context information such as links to a discussion thread, tracking issue, etc. - */ - String value() default ""; -} diff --git a/src/main/java/com/google/api/core/CurrentMillisClock.java b/src/main/java/com/google/api/core/CurrentMillisClock.java deleted file mode 100644 index 068569ec4..000000000 --- a/src/main/java/com/google/api/core/CurrentMillisClock.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.core; - -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.util.concurrent.TimeUnit; - -/** - * Implementation of the {@link ApiClock} interface, which uses {@link System#currentTimeMillis()} - * as time source. - */ -public final class CurrentMillisClock implements ApiClock, Serializable { - - private static final long serialVersionUID = -6019259882852183285L; - private static final ApiClock DEFAULT_CLOCK = new CurrentMillisClock(); - - public static ApiClock getDefaultClock() { - return DEFAULT_CLOCK; - } - - private CurrentMillisClock() {} - - @Override - public long nanoTime() { - return TimeUnit.NANOSECONDS.convert(millisTime(), TimeUnit.MILLISECONDS); - } - - @Override - public long millisTime() { - return System.currentTimeMillis(); - } - - private Object readResolve() throws ObjectStreamException { - return DEFAULT_CLOCK; - } -} diff --git a/src/main/java/com/google/api/core/ForwardingApiFuture.java b/src/main/java/com/google/api/core/ForwardingApiFuture.java deleted file mode 100644 index 95922bf14..000000000 --- a/src/main/java/com/google/api/core/ForwardingApiFuture.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class ForwardingApiFuture implements ApiFuture { - private final ApiFuture delegate; - - public ForwardingApiFuture(ApiFuture delegate) { - this.delegate = delegate; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return delegate.cancel(mayInterruptIfRunning); - } - - @Override - public T get() throws InterruptedException, ExecutionException { - return delegate.get(); - } - - @Override - public T get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return delegate.get(timeout, unit); - } - - @Override - public boolean isCancelled() { - return delegate.isCancelled(); - } - - @Override - public boolean isDone() { - return delegate.isDone(); - } - - @Override - public void addListener(Runnable listener, Executor executor) { - delegate.addListener(listener, executor); - } -} diff --git a/src/main/java/com/google/api/core/InternalApi.java b/src/main/java/com/google/api/core/InternalApi.java deleted file mode 100644 index f0777f97a..000000000 --- a/src/main/java/com/google/api/core/InternalApi.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotates a program element (class, method, package etc) which is internal to its containing - * library, not part of the public API, and should not be used by users of the library. - * - *

- * This annotation only makes sense on APIs that are not private. Its existence is necessary because - * Java does not have a visibility level for code within a compilation unit. - * - *

- * Adding this annotation to an API is considered API-breaking. - */ -@BetaApi -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE -}) -@Documented -public @interface InternalApi { - /** - * Context information such as "internal to library", "for testing", etc. - */ - String value() default ""; -} diff --git a/src/main/java/com/google/api/core/InternalExtensionOnly.java b/src/main/java/com/google/api/core/InternalExtensionOnly.java deleted file mode 100644 index ad78d3bfd..000000000 --- a/src/main/java/com/google/api/core/InternalExtensionOnly.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates a public API that is stable for callers to use, but has no guarantee of stability for - * extension. Consequently, the API should only be extended within the package containing the API. - * - *

- * For example: - *

    - *
  • An interface marked with this annotation can have new methods added to it.
  • - *
  • A non-final class with this annotation can be marked final.
  • - *
  • A class with this annotation can have new abstract methods added.
  • - *
  • a non-final method with this annotation can be marked final.
  • - *
- * - *

- * The list above is just for illustration purposes and is not exhaustive. - * - *

- * Adding this annotation to an API is considered API-breaking. - */ -@BetaApi -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE -}) -@Documented -public @interface InternalExtensionOnly { - /** - * Context information on why the interface/class is annotated with InternalExtensionOnly. - */ - String value() default ""; -} diff --git a/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java b/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java deleted file mode 100644 index 97eddd5ca..000000000 --- a/src/main/java/com/google/api/core/ListenableFutureToApiFuture.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.util.concurrent.ForwardingListenableFuture.SimpleForwardingListenableFuture; -import com.google.common.util.concurrent.ListenableFuture; - -/** - * INTERNAL USE ONLY. Adapter from Guava ListenableFuture to GAX ApiFuture. - */ -@InternalApi -public class ListenableFutureToApiFuture extends SimpleForwardingListenableFuture - implements ApiFuture { - public ListenableFutureToApiFuture(ListenableFuture delegate) { - super(delegate); - } -} diff --git a/src/main/java/com/google/api/core/NanoClock.java b/src/main/java/com/google/api/core/NanoClock.java deleted file mode 100644 index 8b2c04f6d..000000000 --- a/src/main/java/com/google/api/core/NanoClock.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.util.concurrent.TimeUnit; - -/** Default implementation of the ApiClock interface, using call to System.nanoTime(). */ -public final class NanoClock implements ApiClock, Serializable { - - private static final ApiClock DEFAULT_CLOCK = new NanoClock(); - private static final long serialVersionUID = 5541462688633944865L; - - public static ApiClock getDefaultClock() { - return DEFAULT_CLOCK; - } - - private NanoClock() {} - - @Override - public final long nanoTime() { - return System.nanoTime(); - } - - @Override - public final long millisTime() { - return TimeUnit.MILLISECONDS.convert(nanoTime(), TimeUnit.NANOSECONDS); - } - - private Object readResolve() throws ObjectStreamException { - return DEFAULT_CLOCK; - } -} diff --git a/src/main/java/com/google/api/core/SettableApiFuture.java b/src/main/java/com/google/api/core/SettableApiFuture.java deleted file mode 100644 index eab25a744..000000000 --- a/src/main/java/com/google/api/core/SettableApiFuture.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -/** - * An {@link ApiFuture} whose result can be set. Similar to Guava's {@code SettableFuture}, but - * redeclared so that Guava could be shaded. - */ -public final class SettableApiFuture extends AbstractApiFuture { - - private SettableApiFuture() {} - - public static SettableApiFuture create() { - return new SettableApiFuture<>(); - } - - @Override - public boolean set(V value) { - return super.set(value); - } - - @Override - public boolean setException(Throwable throwable) { - return super.setException(throwable); - } -} diff --git a/src/main/java/com/google/api/pathtemplate/PathTemplate.java b/src/main/java/com/google/api/pathtemplate/PathTemplate.java deleted file mode 100644 index 970fa510e..000000000 --- a/src/main/java/com/google/api/pathtemplate/PathTemplate.java +++ /dev/null @@ -1,1192 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.pathtemplate; - -import com.google.auto.value.AutoValue; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nullable; - -/** - * Represents a path template. - * - *

- * Templates use the syntax of the API platform; see the protobuf of HttpRule for details. A - * template consists of a sequence of literals, wildcards, and variable bindings, where each binding - * can have a sub-path. A string representation can be parsed into an instance of - * {@link PathTemplate}, which can then be used to perform matching and instantiation. - * - *

- * Matching and instantiation deals with unescaping and escaping using URL encoding rules. For - * example, if a template variable for a single segment is instantiated with a string like - * {@code "a/b"}, the slash will be escaped to {@code "%2f"}. (Note that slash will not be escaped - * for a multiple-segment variable, but other characters will). The literals in the template itself - * are not escaped automatically, and must be already URL encoded. - * - *

- * Here is an example for a template using simple variables: - * - *

- *   PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}");
- *   assert template.matches("v2/shelves") == false;
- *   Map<String, String> values = template.match("v1/shelves/s1/books/b1");
- *   Map<String, String> expectedValues = new HashMap<>();
- *   expectedValues.put("shelf", "s1");
- *   expectedValues.put("book", "b1");
- *   assert values.equals(expectedValues);
- *   assert template.instantiate(values).equals("v1/shelves/s1/books/b1");
- * 
- * - * Templates can use variables which match sub-paths. Example: - * - *
- *   PathTemplate template = PathTemplate.create("v1/{name=shelves/*/books/*}"};
- *   assert template.match("v1/shelves/books/b1") == null;
- *   Map<String, String> expectedValues = new HashMap<>();
- *   expectedValues.put("name", "shelves/s1/books/b1");
- *   assert template.match("v1/shelves/s1/books/b1").equals(expectedValues);
- * 
- * - * Path templates can also be used with only wildcards. Each wildcard is associated with an implicit - * variable {@code $n}, where n is the zero-based position of the wildcard. Example: - * - *
- *   PathTemplate template = PathTemplate.create("shelves/*/books/*"};
- *   assert template.match("shelves/books/b1") == null;
- *   Map<String, String> values = template.match("v1/shelves/s1/books/b1");
- *   Map<String, String> expectedValues = new HashMap<>();
- *   expectedValues.put("$0", s1");
- *   expectedValues.put("$1", "b1");
- *   assert values.equals(expectedValues);
- * 
- * - * Paths input to matching can use URL relative syntax to indicate a host name by prefixing the host - * name, as in {@code //somewhere.io/some/path}. The host name is matched into the special variable - * {@link #HOSTNAME_VAR}. Patterns are agnostic about host names, and the same pattern can be used - * for URL relative syntax and simple path syntax: - * - *
- *   PathTemplate template = PathTemplate.create("shelves/*"};
- *   Map<String, String> expectedValues = new HashMap<>();
- *   expectedValues.put(PathTemplate.HOSTNAME_VAR, "//somewhere.io");
- *   expectedValues.put("$0", s1");
- *   assert template.match("//somewhere.io/shelves/s1").equals(expectedValues);
- *   expectedValues.clear();
- *   expectedValues.put("$0", s1");
- *   assert template.match("shelves/s1").equals(expectedValues);
- * 
- * - * For the representation of a resource name see {@link TemplatedResourceName}, which is - * based on path templates. - */ -public class PathTemplate { - - /** - * A constant identifying the special variable used for endpoint bindings in the result of - * {@link #matchFromFullName(String)}. It may also contain protocol string, if its provided in the - * input. - */ - public static final String HOSTNAME_VAR = "$hostname"; - - // A regexp to match a custom verb at the end of a path. - private static final Pattern CUSTOM_VERB_PATTERN = Pattern.compile(":([^/*}{=]+)$"); - - // A regex to match a hostname with or without protocol. - private static final Pattern HOSTNAME_PATTERN = Pattern.compile("^(\\w+:)?//"); - - // A splitter on slash. - private static final Splitter SLASH_SPLITTER = Splitter.on('/').trimResults(); - - // A regex to match the valid complex resource ID delimiters. - private static final Pattern COMPLEX_DELIMITER_PATTERN = Pattern.compile("[_\\-\\.~]"); - - // A regex to match multiple complex resource ID delimiters. - private static final Pattern MULTIPLE_COMPLEX_DELIMITER_PATTERN = - Pattern.compile("\\}[_\\-\\.~]{2,}\\{"); - - // A regex to match a missing complex resource ID delimiter. - private static final Pattern MISSING_COMPLEX_DELIMITER_PATTERN = Pattern.compile("\\}\\{"); - - // A regex to match invalid complex resource ID delimiters. - private static final Pattern INVALID_COMPLEX_DELIMITER_PATTERN = - Pattern.compile("\\}[^_\\-\\.~]\\{"); - - // A regex to match a closing segment (end brace) followed by one complex resource ID delimiter. - private static final Pattern END_SEGMENT_COMPLEX_DELIMITER_PATTERN = - Pattern.compile("\\}[_\\-\\.~]{1}"); - - // Helper Types - // ============ - - /** Specifies a path segment kind. */ - enum SegmentKind { - /** A literal path segment. */ - LITERAL, - - /** A custom verb. Can only appear at the end of path. */ - CUSTOM_VERB, - - /** A simple wildcard ('*'). */ - WILDCARD, - - /** A path wildcard ('**'). */ - PATH_WILDCARD, - - /** A field binding start. */ - BINDING, - - /** A field binding end. */ - END_BINDING, - } - - /** Specifies a path segment. */ - @AutoValue - abstract static class Segment { - - /** A constant for the WILDCARD segment. */ - private static final Segment WILDCARD = create(SegmentKind.WILDCARD, "*"); - - /** A constant for the PATH_WILDCARD segment. */ - private static final Segment PATH_WILDCARD = create(SegmentKind.PATH_WILDCARD, "**"); - - /** A constant for the END_BINDING segment. */ - private static final Segment END_BINDING = create(SegmentKind.END_BINDING, ""); - - /** Creates a segment of given kind and value. */ - private static Segment create(SegmentKind kind, String value) { - return new AutoValue_PathTemplate_Segment(kind, value, ""); - } - - private static Segment wildcardCreate(String complexSeparator) { - return new AutoValue_PathTemplate_Segment( - SegmentKind.WILDCARD, - "*", - !complexSeparator.isEmpty() && COMPLEX_DELIMITER_PATTERN.matcher(complexSeparator).find() - ? complexSeparator - : ""); - } - - /** The path segment kind. */ - abstract SegmentKind kind(); - - /** - * The value for the segment. For literals, custom verbs, and wildcards, this reflects the value - * as it appears in the template. For bindings, this represents the variable of the binding. - */ - abstract String value(); - - abstract String complexSeparator(); - - /** Returns true of this segment is one of the wildcards, */ - boolean isAnyWildcard() { - return kind() == SegmentKind.WILDCARD || kind() == SegmentKind.PATH_WILDCARD; - } - - String separator() { - switch (kind()) { - case CUSTOM_VERB: - return ":"; - case END_BINDING: - return ""; - default: - return "/"; - } - } - } - - /** - * Creates a path template from a string. The string must satisfy the syntax of path templates of - * the API platform; see HttpRule's proto source. - * - * @throws ValidationException if there are errors while parsing the template. - */ - public static PathTemplate create(String template) { - return create(template, true); - } - - /** - * Creates a path template from a string. The string must satisfy the syntax of path templates of - * the API platform; see HttpRule's proto source. Url encoding of template variables is disabled. - * - * @throws ValidationException if there are errors while parsing the template. - */ - public static PathTemplate createWithoutUrlEncoding(String template) { - return create(template, false); - } - - private static PathTemplate create(String template, boolean urlEncoding) { - return new PathTemplate(parseTemplate(template), urlEncoding); - } - - // Instance State and Methods - // ========================== - - // List of segments of this template. - private final ImmutableList segments; - - // Map from variable names to bindings in the template. - private final ImmutableMap bindings; - - // Control use of URL encoding - private final boolean urlEncoding; - - private PathTemplate(Iterable segments, boolean urlEncoding) { - this.segments = ImmutableList.copyOf(segments); - if (this.segments.isEmpty()) { - throw new ValidationException("template cannot be empty."); - } - Map bindings = Maps.newLinkedHashMap(); - for (Segment seg : this.segments) { - if (seg.kind() == SegmentKind.BINDING) { - if (bindings.containsKey(seg.value())) { - throw new ValidationException("Duplicate binding '%s'", seg.value()); - } - bindings.put(seg.value(), seg); - } - } - this.bindings = ImmutableMap.copyOf(bindings); - this.urlEncoding = urlEncoding; - } - - /** Returns the set of variable names used in the template. */ - public Set vars() { - return bindings.keySet(); - } - - /** - * Returns a template for the parent of this template. - * - * @throws ValidationException if the template has no parent. - */ - public PathTemplate parentTemplate() { - int i = segments.size(); - Segment seg = segments.get(--i); - if (seg.kind() == SegmentKind.END_BINDING) { - while (i > 0 && segments.get(--i).kind() != SegmentKind.BINDING) {} - } - if (i == 0) { - throw new ValidationException("template does not have a parent"); - } - return new PathTemplate(segments.subList(0, i), urlEncoding); - } - - /** - * Returns a template where all variable bindings have been replaced by wildcards, but which is - * equivalent regards matching to this one. - */ - public PathTemplate withoutVars() { - StringBuilder result = new StringBuilder(); - ListIterator iterator = segments.listIterator(); - boolean start = true; - while (iterator.hasNext()) { - Segment seg = iterator.next(); - switch (seg.kind()) { - case BINDING: - case END_BINDING: - break; - default: - if (!start) { - result.append(seg.separator()); - } else { - start = false; - } - result.append(seg.value()); - } - } - return create(result.toString(), urlEncoding); - } - - /** - * Returns a path template for the sub-path of the given variable. Example: - * - *
-   *   PathTemplate template = PathTemplate.create("v1/{name=shelves/*/books/*}");
-   *   assert template.subTemplate("name").toString().equals("shelves/*/books/*");
-   * 
- * - * The returned template will never have named variables, but only wildcards, which are dealt with - * in matching and instantiation using '$n'-variables. See the documentation of - * {@link #match(String)} and {@link #instantiate(Map)}, respectively. - * - *

- * For a variable which has no sub-path, this returns a path template with a single wildcard - * ('*'). - * - * @throws ValidationException if the variable does not exist in the template. - */ - public PathTemplate subTemplate(String varName) { - List sub = Lists.newArrayList(); - boolean inBinding = false; - for (Segment seg : segments) { - if (seg.kind() == SegmentKind.BINDING && seg.value().equals(varName)) { - inBinding = true; - } else if (inBinding) { - if (seg.kind() == SegmentKind.END_BINDING) { - return PathTemplate.create(toSyntax(sub, true), urlEncoding); - } else { - sub.add(seg); - } - } - } - throw new ValidationException( - String.format("Variable '%s' is undefined in template '%s'", varName, this.toRawString())); - } - - /** Returns true of this template ends with a literal. */ - public boolean endsWithLiteral() { - return segments.get(segments.size() - 1).kind() == SegmentKind.LITERAL; - } - - /** Returns true of this template ends with a custom verb. */ - public boolean endsWithCustomVerb() { - return segments.get(segments.size() - 1).kind() == SegmentKind.CUSTOM_VERB; - } - - /** - * Creates a resource name from this template and a path. - * - * @throws ValidationException if the path does not match the template. - */ - public TemplatedResourceName parse(String path) { - return TemplatedResourceName.create(this, path); - } - - /** - * Returns the name of a singleton variable used by this template. If the template does not - * contain a single variable, returns null. - */ - @Nullable - public String singleVar() { - if (bindings.size() == 1) { - return bindings.entrySet().iterator().next().getKey(); - } - return null; - } - - // Template Matching - // ================= - - /** - * Throws a ValidationException if the template doesn't match the path. The exceptionMessagePrefix - * parameter will be prepended to the ValidationException message. - */ - public void validate(String path, String exceptionMessagePrefix) { - if (!matches(path)) { - throw new ValidationException( - String.format( - "%s: Parameter \"%s\" must be in the form \"%s\"", - exceptionMessagePrefix, - path, - this.toString())); - } - } - - /** - * Matches the path, returning a map from variable names to matched values. All matched values - * will be properly unescaped using URL encoding rules. If the path does not match the template, - * throws a ValidationException. The exceptionMessagePrefix parameter will be prepended to the - * ValidationException message. - * - *

- * If the path starts with '//', the first segment will be interpreted as a host name and stored - * in the variable {@link #HOSTNAME_VAR}. - * - *

- * See the {@link PathTemplate} class documentation for examples. - * - *

- * For free wildcards in the template, the matching process creates variables named '$n', where - * 'n' is the wildcard's position in the template (starting at n=0). For example: - * - *

-   *   PathTemplate template = PathTemplate.create("shelves/*/books/*");
-   *   Map<String, String> expectedValues = new HashMap<>();
-   *   expectedValues.put("$0", "s1");
-   *   expectedValues.put("$1", "b1");
-   *   assert template.validatedMatch("shelves/s1/books/b2", "User exception string")
-   *              .equals(expectedValues);
-   *   expectedValues.clear();
-   *   expectedValues.put(HOSTNAME_VAR, "//somewhere.io");
-   *   expectedValues.put("$0", "s1");
-   *   expectedValues.put("$1", "b1");
-   *   assert template.validatedMatch("//somewhere.io/shelves/s1/books/b2", "User exception string")
-   *              .equals(expectedValues);
-   * 
- * - * All matched values will be properly unescaped using URL encoding rules (so long as URL encoding - * has not been disabled by the {@link #createWithoutUrlEncoding} method). - */ - public Map validatedMatch(String path, String exceptionMessagePrefix) { - Map matchMap = match(path); - if (matchMap == null) { - throw new ValidationException( - String.format( - "%s: Parameter \"%s\" must be in the form \"%s\"", - exceptionMessagePrefix, - path, - this.toString())); - } - return matchMap; - } - - /** Returns true if the template matches the path. */ - public boolean matches(String path) { - return match(path) != null; - } - - /** - * Matches the path, returning a map from variable names to matched values. All matched values - * will be properly unescaped using URL encoding rules. If the path does not match the template, - * null is returned. - * - *

- * If the path starts with '//', the first segment will be interpreted as a host name and stored - * in the variable {@link #HOSTNAME_VAR}. - * - *

- * See the {@link PathTemplate} class documentation for examples. - * - *

- * For free wildcards in the template, the matching process creates variables named '$n', where - * 'n' is the wildcard's position in the template (starting at n=0). For example: - * - *

-   *   PathTemplate template = PathTemplate.create("shelves/*/books/*");
-   *   Map<String, String> expectedValues = new HashMap<>();
-   *   expectedValues.put("$0", "s1");
-   *   expectedValues.put("$1", "b1");
-   *   assert template.match("shelves/s1/books/b2").equals(expectedValues);
-   *   expectedValues.clear();
-   *   expectedValues.put(HOSTNAME_VAR, "//somewhere.io");
-   *   expectedValues.put("$0", "s1");
-   *   expectedValues.put("$1", "b1");
-   *   assert template.match("//somewhere.io/shelves/s1/books/b2").equals(expectedValues);
-   * 
- * - * All matched values will be properly unescaped using URL encoding rules (so long as URL encoding - * has not been disabled by the {@link #createWithoutUrlEncoding} method). - */ - @Nullable - public Map match(String path) { - return match(path, false); - } - - /** - * Matches the path, where the first segment is interpreted as the host name regardless of whether - * it starts with '//' or not. Example: - * - *
-   *   Map<String, String> expectedValues = new HashMap<>();
-   *   expectedValues.put(HOSTNAME_VAR, "//somewhere.io");
-   *   expectedValues.put("name", "shelves/s1");
-   *   assert template("{name=shelves/*}").matchFromFullName("somewhere.io/shelves/s1")
-   *            .equals(expectedValues);
-   * 
- */ - @Nullable - public Map matchFromFullName(String path) { - return match(path, true); - } - - // Matches a path. - private Map match(String path, boolean forceHostName) { - // Quick check for trailing custom verb. - Segment last = segments.get(segments.size() - 1); - if (last.kind() == SegmentKind.CUSTOM_VERB) { - Matcher matcher = CUSTOM_VERB_PATTERN.matcher(path); - if (!matcher.find() || !decodeUrl(matcher.group(1)).equals(last.value())) { - return null; - } - path = path.substring(0, matcher.start(0)); - } - - Matcher matcher = HOSTNAME_PATTERN.matcher(path); - boolean withHostName = matcher.find(); - if (withHostName) { - path = matcher.replaceFirst(""); - } - List input = SLASH_SPLITTER.splitToList(path); - int inPos = 0; - Map values = Maps.newLinkedHashMap(); - if (withHostName || forceHostName) { - if (input.isEmpty()) { - return null; - } - String hostName = input.get(inPos++); - if (withHostName) { - // Put the // back, so we can distinguish this case from forceHostName. - hostName = matcher.group(0) + hostName; - } - values.put(HOSTNAME_VAR, hostName); - } - if (withHostName) { - inPos = alignInputToAlignableSegment(input, inPos, segments.get(0)); - } - if (!match(input, inPos, segments, 0, values)) { - return null; - } - return ImmutableMap.copyOf(values); - } - - // Aligns input to start of literal value of literal or binding segment if input contains - // hostname. - private int alignInputToAlignableSegment(List input, int inPos, Segment segment) { - switch (segment.kind()) { - case BINDING: - inPos = alignInputPositionToLiteral(input, inPos, segment.value() + "s"); - return inPos + 1; - case LITERAL: - return alignInputPositionToLiteral(input, inPos, segment.value()); - } - return inPos; - } - - // Aligns input to start of literal value if input contains hostname. - private int alignInputPositionToLiteral( - List input, int inPos, String literalSegmentValue) { - for (; inPos < input.size(); inPos++) { - if (literalSegmentValue.equals(input.get(inPos))) { - return inPos; - } - } - return inPos; - } - - // Tries to match the input based on the segments at given positions. Returns a boolean - // indicating whether the match was successful. - private boolean match( - List input, - int inPos, - List segments, - int segPos, - Map values) { - String currentVar = null; - List modifiableInput = new ArrayList<>(input); - while (segPos < segments.size()) { - Segment seg = segments.get(segPos++); - switch (seg.kind()) { - case END_BINDING: - // End current variable binding scope. - currentVar = null; - continue; - case BINDING: - // Start variable binding scope. - currentVar = seg.value(); - continue; - case CUSTOM_VERB: - // This is the final segment, and this check should have already been performed by the - // caller. The matching value is no longer present in the input. - break; - case LITERAL: - case WILDCARD: - if (inPos >= modifiableInput.size()) { - // End of input - return false; - } - // Check literal match. - String next = decodeUrl(modifiableInput.get(inPos++)); - if (seg.kind() == SegmentKind.LITERAL) { - if (!seg.value().equals(next)) { - // Literal does not match. - return false; - } - } - if (seg.kind() == SegmentKind.WILDCARD && !seg.complexSeparator().isEmpty()) { - // Parse the complex resource separators one by one. - int complexSeparatorIndex = next.indexOf(seg.complexSeparator()); - if (complexSeparatorIndex >= 0) { - modifiableInput.add(inPos, next.substring(complexSeparatorIndex + 1)); - next = next.substring(0, complexSeparatorIndex); - modifiableInput.set(inPos - 1, next); - } else { - // No complex resource ID separator found in the literal when we expected one. - return false; - } - } - if (currentVar != null) { - // Create or extend current match - values.put(currentVar, concatCaptures(values.get(currentVar), next)); - } - break; - case PATH_WILDCARD: - // Compute the number of additional input the ** can consume. This - // is possible because we restrict patterns to have only one **. - int segsToMatch = 0; - for (int i = segPos; i < segments.size(); i++) { - switch (segments.get(i).kind()) { - case BINDING: - case END_BINDING: - // skip - continue; - default: - segsToMatch++; - } - } - int available = (modifiableInput.size() - inPos) - segsToMatch; - // If this segment is empty, make sure it is still captured. - if (available == 0 && !values.containsKey(currentVar)) { - values.put(currentVar, ""); - } - while (available-- > 0) { - values.put( - currentVar, - concatCaptures(values.get(currentVar), decodeUrl(modifiableInput.get(inPos++)))); - } - } - } - return inPos == modifiableInput.size(); - } - - private static String concatCaptures(@Nullable String cur, String next) { - return cur == null ? next : cur + "/" + next; - } - - // Template Instantiation - // ====================== - - /** - * Instantiate the template based on the given variable assignment. Performs proper URL escaping - * of variable assignments. - * - *

- * Note that free wildcards in the template must have bindings of '$n' variables, where 'n' is the - * position of the wildcard (starting at 0). See the documentation of {@link #match(String)} for - * details. - * - * @throws ValidationException if a variable occurs in the template without a binding. - */ - public String instantiate(Map values) { - return instantiate(values, false); - } - - /** Shortcut for {@link #instantiate(Map)} with a vararg parameter for keys and values. */ - public String instantiate(String... keysAndValues) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (int i = 0; i < keysAndValues.length; i += 2) { - builder.put(keysAndValues[i], keysAndValues[i + 1]); - } - return instantiate(builder.build()); - } - - /** - * Same like {@link #instantiate(Map)} but allows for unbound variables, which are substituted - * using their original syntax. Example: - * - *

-   *   PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}");
-   *   Map<String, String> partialMap = new HashMap<>();
-   *   partialMap.put("shelf", "s1");
-   *   assert template.instantiatePartial(partialMap).equals("v1/shelves/s1/books/{book}");
-   * 
- * - * The result of this call can be used to create a new template. - */ - public String instantiatePartial(Map values) { - return instantiate(values, true); - } - - private String instantiate(Map values, boolean allowPartial) { - StringBuilder result = new StringBuilder(); - if (values.containsKey(HOSTNAME_VAR)) { - result.append(values.get(HOSTNAME_VAR)); - result.append('/'); - } - boolean continueLast = true; // Whether to not append separator - boolean skip = false; // Whether we are substituting a binding and segments shall be skipped. - ListIterator iterator = segments.listIterator(); - while (iterator.hasNext()) { - Segment seg = iterator.next(); - if (!skip && !continueLast) { - result.append(seg.separator()); - } - continueLast = false; - switch (seg.kind()) { - case BINDING: - String var = seg.value(); - String value = values.get(seg.value()); - if (value == null) { - if (!allowPartial) { - throw new ValidationException( - String.format("Unbound variable '%s'. Bindings: %s", var, values)); - } - // Append pattern to output - if (var.startsWith("$")) { - // Eliminate positional variable. - result.append(iterator.next().value()); - iterator.next(); - continue; - } - result.append('{'); - result.append(seg.value()); - result.append('='); - continueLast = true; - continue; - } - Segment next = iterator.next(); - Segment nextNext = iterator.next(); - boolean pathEscape = - next.kind() == SegmentKind.PATH_WILDCARD - || nextNext.kind() != SegmentKind.END_BINDING; - restore(iterator, iterator.nextIndex() - 2); - if (!pathEscape) { - result.append(encodeUrl(value)); - } else { - // For a path wildcard or path of length greater 1, split the value and escape - // every sub-segment. - boolean first = true; - for (String subSeg : SLASH_SPLITTER.split(value)) { - if (!first) { - result.append('/'); - } - first = false; - result.append(encodeUrl(subSeg)); - } - } - skip = true; - continue; - case END_BINDING: - if (!skip) { - result.append('}'); - } - skip = false; - continue; - default: - if (!skip) { - result.append(seg.value()); - } - } - } - return result.toString(); - } - - // Positional Matching and Instantiation - // ===================================== - - /** - * Instantiates the template from the given positional parameters. The template must not be build - * from named bindings, but only contain wildcards. Each parameter position corresponds to a - * wildcard of the according position in the template. - */ - public String encode(String... values) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - int i = 0; - for (String value : values) { - builder.put("$" + i++, value); - } - // We will get an error if there are named bindings which are not reached by values. - return instantiate(builder.build()); - } - - /** - * Matches the template into a list of positional values. The template must not be build from - * named bindings, but only contain wildcards. For each wildcard in the template, a value is - * returned at corresponding position in the list. - */ - public List decode(String path) { - Map match = match(path); - if (match == null) { - throw new IllegalArgumentException( - String.format("template '%s' does not match '%s'", this, path)); - } - List result = Lists.newArrayList(); - for (Map.Entry entry : match.entrySet()) { - String key = entry.getKey(); - if (!key.startsWith("$")) { - throw new IllegalArgumentException("template must not contain named bindings"); - } - int i = Integer.parseInt(key.substring(1)); - while (result.size() <= i) { - result.add(""); - } - result.set(i, entry.getValue()); - } - return ImmutableList.copyOf(result); - } - - // Template Parsing - // ================ - - private static ImmutableList parseTemplate(String template) { - // Skip useless leading slash. - if (template.startsWith("/")) { - template = template.substring(1); - } - - // Extract trailing custom verb. - Matcher matcher = CUSTOM_VERB_PATTERN.matcher(template); - String customVerb = null; - if (matcher.find()) { - customVerb = matcher.group(1); - template = template.substring(0, matcher.start(0)); - } - - ImmutableList.Builder builder = ImmutableList.builder(); - String varName = null; - int freeWildcardCounter = 0; - int pathWildCardBound = 0; - - for (String seg : Splitter.on('/').trimResults().split(template)) { - if (COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(0, 1)).find() - || COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(seg.length() - 1)).find()) { - throw new ValidationException("parse error: invalid begin or end character in '%s'", seg); - } - // Disallow zero or multiple delimiters between variable names. - if (MULTIPLE_COMPLEX_DELIMITER_PATTERN.matcher(seg).find() - || MISSING_COMPLEX_DELIMITER_PATTERN.matcher(seg).find()) { - throw new ValidationException( - "parse error: missing or 2+ consecutive delimiter characters in '%s'", seg); - } - // If segment starts with '{', a binding group starts. - boolean bindingStarts = seg.startsWith("{"); - boolean implicitWildcard = false; - boolean complexDelimiterFound = false; - if (bindingStarts) { - if (varName != null) { - throw new ValidationException("parse error: nested binding in '%s'", template); - } - seg = seg.substring(1); - - // Check for invalid complex resource ID delimiters. - if (INVALID_COMPLEX_DELIMITER_PATTERN.matcher(seg).find()) { - throw new ValidationException( - "parse error: invalid complex resource ID delimiter character in '%s'", seg); - } - - Matcher complexPatternDelimiterMatcher = END_SEGMENT_COMPLEX_DELIMITER_PATTERN.matcher(seg); - complexDelimiterFound = complexPatternDelimiterMatcher.find(); - - // Look for complex resource names. - // Need to handle something like "{user_a}~{user_b}". - if (complexDelimiterFound) { - builder.addAll(parseComplexResourceId(seg)); - } else { - int i = seg.indexOf('='); - if (i <= 0) { - // Possibly looking at something like "{name}" with implicit wildcard. - if (seg.endsWith("}")) { - // Remember to add an implicit wildcard later. - implicitWildcard = true; - varName = seg.substring(0, seg.length() - 1).trim(); - seg = seg.substring(seg.length() - 1).trim(); - } else { - throw new ValidationException( - "parse error: invalid binding syntax in '%s'", template); - } - } else { - // Looking at something like "{name=wildcard}". - varName = seg.substring(0, i).trim(); - seg = seg.substring(i + 1).trim(); - } - builder.add(Segment.create(SegmentKind.BINDING, varName)); - } - } - - if (!complexDelimiterFound) { - // If segment ends with '}', a binding group ends. Remove the brace and remember. - boolean bindingEnds = seg.endsWith("}"); - if (bindingEnds) { - seg = seg.substring(0, seg.length() - 1).trim(); - } - - // Process the segment, after stripping off "{name=.." and "..}". - switch (seg) { - case "**": - case "*": - if ("**".equals(seg)) { - pathWildCardBound++; - } - Segment wildcard = seg.length() == 2 ? Segment.PATH_WILDCARD : Segment.WILDCARD; - if (varName == null) { - // Not in a binding, turn wildcard into implicit binding. - // "*" => "{$n=*}" - builder.add(Segment.create(SegmentKind.BINDING, "$" + freeWildcardCounter)); - freeWildcardCounter++; - builder.add(wildcard); - builder.add(Segment.END_BINDING); - } else { - builder.add(wildcard); - } - break; - case "": - if (!bindingEnds) { - throw new ValidationException( - "parse error: empty segment not allowed in '%s'", template); - } - // If the wildcard is implicit, seg will be empty. Just continue. - break; - default: - builder.add(Segment.create(SegmentKind.LITERAL, seg)); - } - - // End a binding. - if (bindingEnds && !complexDelimiterFound) { - // Reset varName to null for next binding. - varName = null; - - if (implicitWildcard) { - // Looking at something like "{var}". Insert an implicit wildcard, as it is the same - // as "{var=*}". - builder.add(Segment.WILDCARD); - } - builder.add(Segment.END_BINDING); - } - - if (pathWildCardBound > 1) { - // Report restriction on number of '**' in the pattern. There can be only one, which - // enables non-backtracking based matching. - throw new ValidationException( - "parse error: pattern must not contain more than one path wildcard ('**') in '%s'", - template); - } - } - } - - if (customVerb != null) { - builder.add(Segment.create(SegmentKind.CUSTOM_VERB, customVerb)); - } - return builder.build(); - } - - private static List parseComplexResourceId(String seg) { - List segments = new ArrayList<>(); - List separatorIndices = new ArrayList<>(); - - Matcher complexPatternDelimiterMatcher = END_SEGMENT_COMPLEX_DELIMITER_PATTERN.matcher(seg); - boolean delimiterFound = complexPatternDelimiterMatcher.find(); - - while (delimiterFound) { - int delimiterIndex = complexPatternDelimiterMatcher.start(); - if (seg.substring(delimiterIndex).startsWith("}")) { - delimiterIndex += 1; - } - String currDelimiter = seg.substring(delimiterIndex, delimiterIndex + 1); - if (!COMPLEX_DELIMITER_PATTERN.matcher(currDelimiter).find()) { - throw new ValidationException( - "parse error: invalid complex ID delimiter '%s' in '%s'", currDelimiter, seg); - } - separatorIndices.add(currDelimiter); - delimiterFound = complexPatternDelimiterMatcher.find(delimiterIndex + 1); - } - // The last entry does not have a delimiter. - separatorIndices.add(""); - - String subVarName = null; - Iterable complexSubsegments = - Splitter.onPattern("\\}[_\\-\\.~]").trimResults().split(seg); - boolean complexSegImplicitWildcard = false; - int currIteratorIndex = 0; - for (String complexSeg : complexSubsegments) { - boolean subsegmentBindingStarts = complexSeg.startsWith("{"); - if (subsegmentBindingStarts) { - if (subVarName != null) { - throw new ValidationException("parse error: nested binding in '%s'", complexSeg); - } - complexSeg = complexSeg.substring(1); - } - subVarName = complexSeg.trim(); - - boolean subBindingEnds = complexSeg.endsWith("}"); - int i = complexSeg.indexOf('='); - if (i <= 0) { - // Possibly looking at something like "{name}" with implicit wildcard. - if (subBindingEnds) { - // Remember to add an implicit wildcard later. - complexSegImplicitWildcard = true; - subVarName = complexSeg.substring(0, complexSeg.length() - 1).trim(); - complexSeg = complexSeg.substring(complexSeg.length() - 1).trim(); - } - } else { - // Looking at something like "{name=wildcard}". - subVarName = complexSeg.substring(0, i).trim(); - complexSeg = complexSeg.substring(i + 1).trim(); - if (complexSeg.equals("**")) { - throw new ValidationException( - "parse error: wildcard path not allowed in complex ID resource '%s'", subVarName); - } - } - String complexDelimiter = - currIteratorIndex < separatorIndices.size() - ? separatorIndices.get(currIteratorIndex) - : ""; - segments.add(Segment.create(SegmentKind.BINDING, subVarName)); - segments.add(Segment.wildcardCreate(complexDelimiter)); - segments.add(Segment.END_BINDING); - subVarName = null; - - currIteratorIndex++; - } - return segments; - } - - // Helpers - // ======= - - private String encodeUrl(String text) { - if (urlEncoding) { - try { - return URLEncoder.encode(text, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new ValidationException("UTF-8 encoding is not supported on this platform"); - } - } else { - // When encoding is disabled, we accept any character except '/' - final String INVALID_CHAR = "/"; - if (text.contains(INVALID_CHAR)) { - throw new ValidationException( - "Invalid character \"" + INVALID_CHAR + "\" in path section \"" + text + "\"."); - } - return text; - } - } - - private String decodeUrl(String url) { - if (urlEncoding) { - try { - return URLDecoder.decode(url, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new ValidationException("UTF-8 encoding is not supported on this platform"); - } - } else { - return url; - } - } - - // Checks for the given segments kind. On success, consumes them. Otherwise leaves - // the list iterator in its state. - private static boolean peek(ListIterator segments, SegmentKind... kinds) { - int start = segments.nextIndex(); - boolean success = false; - for (SegmentKind kind : kinds) { - if (!segments.hasNext() || segments.next().kind() != kind) { - success = false; - break; - } - } - if (success) { - return true; - } - restore(segments, start); - return false; - } - - // Restores a list iterator back to a given index. - private static void restore(ListIterator segments, int index) { - while (segments.nextIndex() > index) { - segments.previous(); - } - } - - // Equality and String Conversion - // ============================== - - /** Returns a pretty version of the template as a string. */ - @Override - public String toString() { - return toSyntax(segments, true); - } - - /** - * Returns a raw version of the template as a string. This renders the template in its internal, - * normalized form. - */ - public String toRawString() { - return toSyntax(segments, false); - } - - private static String toSyntax(List segments, boolean pretty) { - StringBuilder result = new StringBuilder(); - boolean continueLast = true; // if true, no slash is appended. - ListIterator iterator = segments.listIterator(); - while (iterator.hasNext()) { - Segment seg = iterator.next(); - if (!continueLast) { - result.append(seg.separator()); - } - continueLast = false; - switch (seg.kind()) { - case BINDING: - if (pretty && seg.value().startsWith("$")) { - // Remove the internal binding. - seg = iterator.next(); // Consume wildcard - result.append(seg.value()); - iterator.next(); // Consume END_BINDING - continue; - } - result.append('{'); - result.append(seg.value()); - if (pretty && peek(iterator, SegmentKind.WILDCARD, SegmentKind.END_BINDING)) { - // Reduce {name=*} to {name}. - result.append('}'); - continue; - } - result.append('='); - continueLast = true; - continue; - case END_BINDING: - result.append('}'); - continue; - default: - result.append(seg.value()); - continue; - } - } - return result.toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof PathTemplate)) { - return false; - } - PathTemplate other = (PathTemplate) obj; - return Objects.equals(segments, other.segments); - } - - @Override - public int hashCode() { - return segments.hashCode(); - } -} diff --git a/src/main/java/com/google/api/pathtemplate/TemplatedResourceName.java b/src/main/java/com/google/api/pathtemplate/TemplatedResourceName.java deleted file mode 100644 index bbbedeaeb..000000000 --- a/src/main/java/com/google/api/pathtemplate/TemplatedResourceName.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.pathtemplate; - -import com.google.api.core.BetaApi; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import javax.annotation.Nullable; - -/** - * Class for representing and working with resource names. - * - *

- * A resource name is represented by {@link PathTemplate}, an assignment to variables in the - * template, and an optional endpoint. The {@code ResourceName} class implements the map interface - * (unmodifiable) to work with the variable assignments, and has methods to reproduce the string - * representation of the name, to construct new names, and to dereference names into resources. - * - *

- * As a resource name essentially represents a match of a path template against a string, it can be - * also used for other purposes than naming resources. However, not all provided methods may make - * sense in all applications. - * - *

- * Usage examples: - * - *

- *   PathTemplate template = PathTemplate.create("shelves/*/books/*");
- *   TemplatedResourceName resourceName = TemplatedResourceName.create(template, "shelves/s1/books/b1");
- *   assert resourceName.get("$1").equals("b1");
- *   assert resourceName.parentName().toString().equals("shelves/s1/books");
- * 
- */ -public class TemplatedResourceName implements Map { - - // ResourceName Resolver - // ===================== - - /** - * Represents a resource name resolver which can be registered with this class. - */ - public interface Resolver { - /** - * Resolves the resource name into a resource by calling the underlying API. - */ - T resolve(Class resourceType, TemplatedResourceName name, @Nullable String version); - } - - // The registered resource name resolver. - // TODO(wrwg): its a bit spooky to have this static global. Think of ways to - // configure this from the outside instead if programmatically (e.g. java properties). - private static volatile Resolver resourceNameResolver = - new Resolver() { - @Override - public T resolve(Class resourceType, TemplatedResourceName name, String version) { - throw new IllegalStateException( - "No resource name resolver is registered in ResourceName class."); - } - }; - - /** - * Sets the resource name resolver which is used by the {@link #resolve(Class, String)} method. By - * default, no resolver is registered. - */ - public static void registerResourceNameResolver(Resolver resolver) { - resourceNameResolver = resolver; - } - - // ResourceName - // ============ - - /** - * Creates a new resource name based on given template and path. The path must match the template, - * otherwise null is returned. - * - * @throws ValidationException if the path does not match the template. - */ - public static TemplatedResourceName create(PathTemplate template, String path) { - Map values = template.match(path); - if (values == null) { - throw new ValidationException("path '%s' does not match template '%s'", path, template); - } - return new TemplatedResourceName(template, values, null); - } - - /** - * Creates a new resource name from a template and a value assignment for variables. - * - * @throws ValidationException if not all variables in the template are bound. - */ - public static TemplatedResourceName create(PathTemplate template, Map values) { - if (!values.keySet().containsAll(template.vars())) { - Set unbound = Sets.newLinkedHashSet(template.vars()); - unbound.removeAll(values.keySet()); - throw new ValidationException("unbound variables: %s", unbound); - } - return new TemplatedResourceName(template, values, null); - } - - /** - * Creates a new resource name based on given template and path, where the path contains an - * endpoint. If the path does not match, null is returned. - */ - @Nullable - public static TemplatedResourceName createFromFullName(PathTemplate template, String path) { - Map values = template.matchFromFullName(path); - if (values == null) { - return null; - } - return new TemplatedResourceName(template, values, null); - } - - private final PathTemplate template; - private final ImmutableMap values; - private final String endpoint; - - private volatile String stringRepr; - - private TemplatedResourceName( - PathTemplate template, Map values, String endpoint) { - this.template = template; - this.values = ImmutableMap.copyOf(values); - this.endpoint = endpoint; - } - - @Override - public String toString() { - if (stringRepr == null) { - stringRepr = template.instantiate(values); - } - return stringRepr; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof TemplatedResourceName)) { - return false; - } - TemplatedResourceName other = (TemplatedResourceName) obj; - return Objects.equals(template, other.template) - && Objects.equals(endpoint, other.endpoint) - && Objects.equals(values, other.values); - } - - @Override - public int hashCode() { - return Objects.hash(template, endpoint, values); - } - - /** - * Gets the template associated with this resource name. - */ - public PathTemplate template() { - return template; - } - - /** - * Checks whether the resource name has an endpoint. - */ - public boolean hasEndpoint() { - return endpoint != null; - } - - /** - * Returns the endpoint of this resource name, or null if none is defined. - */ - @Nullable - public String endpoint() { - return endpoint; - } - - /** - * Returns a resource name with specified endpoint. - */ - public TemplatedResourceName withEndpoint(String endpoint) { - return new TemplatedResourceName(template, values, Preconditions.checkNotNull(endpoint)); - } - - /** - * Returns the parent resource name. For example, if the name is {@code shelves/s1/books/b1}, the - * parent is {@code shelves/s1/books}. - */ - public TemplatedResourceName parentName() { - PathTemplate parentTemplate = template.parentTemplate(); - return new TemplatedResourceName(parentTemplate, values, endpoint); - } - - /** - * Returns true of the resource name starts with the parent resource name, i.e. is a child of the - * parent. - */ - public boolean startsWith(TemplatedResourceName parentName) { - // TODO: more efficient implementation. - return toString().startsWith(parentName.toString()); - } - - /** - * Attempts to resolve a resource name into a resource, by calling the associated API. The - * resource name must have an endpoint. An optional version can be specified to determine in which - * version of the API to call. - */ - public T resolve(Class resourceType, @Nullable String version) { - Preconditions.checkArgument(hasEndpoint(), "Resource name must have an endpoint."); - return resourceNameResolver.resolve(resourceType, this, version); - } - - // Map Interface - // ============= - - @Override - public int size() { - return values.size(); - } - - @Override - public boolean isEmpty() { - return values.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return values.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return values.containsValue(value); - } - - @Override - public String get(Object key) { - return values.get(key); - } - - @Override - @Deprecated - public String put(String key, String value) { - return values.put(key, value); - } - - @Override - @Deprecated - public String remove(Object key) { - return values.remove(key); - } - - @Override - @Deprecated - public void putAll(Map m) { - values.putAll(m); - } - - @Override - @Deprecated - public void clear() { - values.clear(); - } - - @Override - public Set keySet() { - return values.keySet(); - } - - @Override - public Collection values() { - return values.values(); - } - - @Override - public Set> entrySet() { - return values.entrySet(); - } -} diff --git a/src/main/java/com/google/api/pathtemplate/ValidationException.java b/src/main/java/com/google/api/pathtemplate/ValidationException.java deleted file mode 100644 index 13057ca33..000000000 --- a/src/main/java/com/google/api/pathtemplate/ValidationException.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.pathtemplate; - -import java.util.Stack; - -/** - * Exception thrown if there is a validation problem with a path template, http config, or related - * framework methods. Comes as an illegal argument exception subclass. Allows to globally set a - * thread-local validation context description which each exception inherits. - */ -public class ValidationException extends IllegalArgumentException { - - public interface Supplier { - T get(); - } - - private static ThreadLocal>> contextLocal = new ThreadLocal<>(); - - /** - * Sets the validation context description. Each thread has its own description, so this is thread - * safe. - */ - public static void pushCurrentThreadValidationContext(Supplier supplier) { - Stack> stack = contextLocal.get(); - if (stack == null) { - stack = new Stack<>(); - contextLocal.set(stack); - } - stack.push(supplier); - } - - public static void pushCurrentThreadValidationContext(final String context) { - pushCurrentThreadValidationContext( - new Supplier() { - @Override - public String get() { - return context; - } - }); - } - - /** - * Clears the validation context. - */ - public static void popCurrentThreadValidationContext() { - Stack stack = contextLocal.get(); - if (stack != null) { - stack.pop(); - } - } - - /** - * Construct validation exception with implicit context. - */ - public ValidationException(String format, Object... args) { - super(message(contextLocal.get(), format, args)); - } - - private static String message(Stack> context, String format, Object... args) { - if (context == null || context.isEmpty()) { - return String.format(format, args); - } - StringBuilder result = new StringBuilder(); - for (Supplier supplier : context) { - result.append(supplier.get() + ": "); - } - return result.toString() + String.format(format, args); - } -} diff --git a/src/main/java/com/google/api/resourcenames/ResourceName.java b/src/main/java/com/google/api/resourcenames/ResourceName.java deleted file mode 100644 index 8442f4fdd..000000000 --- a/src/main/java/com/google/api/resourcenames/ResourceName.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.resourcenames; - -import java.util.Map; - -/** An interface that generated resource name types must implement. */ -public interface ResourceName { - - /** - * Return the map of each field name to its value. - */ - Map getFieldValuesMap(); - - /** - * Return the String value of the field with name fieldName. Returns null if the fieldName was not - * found. - */ - String getFieldValue(String fieldName); -} diff --git a/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java b/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java deleted file mode 100644 index 13c1967af..000000000 --- a/src/main/java/com/google/api/resourcenames/ResourceNameFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.resourcenames; - -public interface ResourceNameFactory { - - /* Create a new ResourceName from a formatted String representing a ResourceName. */ - T parse(String formattedString); -} diff --git a/src/main/java/com/google/api/resourcenames/UntypedResourceName.java b/src/main/java/com/google/api/resourcenames/UntypedResourceName.java deleted file mode 100644 index 19a6e1e9d..000000000 --- a/src/main/java/com/google/api/resourcenames/UntypedResourceName.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.resourcenames; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import java.util.Map; - -/** - * A class to represent a {@link ResourceName} with an unknown format. This class in intended to - * support the case of a resource name string in an unexpected format - generated resource name - * classes with known formats should be preferred where possible. - */ -public class UntypedResourceName implements ResourceName { - - private final String rawValue; - - private volatile Map fieldValuesMap; - - private UntypedResourceName(String rawValue) { - this.rawValue = Preconditions.checkNotNull(rawValue); - } - - public static UntypedResourceName of(ResourceName resourceName) { - return new UntypedResourceName(resourceName.toString()); - } - - public static UntypedResourceName parse(String formattedString) { - return new UntypedResourceName(formattedString); - } - - public static boolean isParsableFrom(String formattedString) { - return formattedString != null; - } - - /* Returns a map with an empty String "" as the sole key, which maps to the raw value of this ResourceName. */ - @Override - public Map getFieldValuesMap() { - if (fieldValuesMap == null) { - synchronized (this) { - if (fieldValuesMap == null) { - fieldValuesMap = ImmutableMap.of("", rawValue); - } - } - } - return fieldValuesMap; - } - - /* Returns the raw value of this ResourceName iff fieldName.equals(""), else returns null. */ - @Override - public String getFieldValue(String fieldName) { - return getFieldValuesMap().get(""); - } - - @Override - public String toString() { - return rawValue; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof UntypedResourceName) { - UntypedResourceName that = (UntypedResourceName) o; - return this.rawValue.equals(that.rawValue); - } - return false; - } - - @Override - public int hashCode() { - return rawValue.hashCode(); - } -} diff --git a/src/test/java/com/google/api/core/ApiFuturesTest.java b/src/test/java/com/google/api/core/ApiFuturesTest.java deleted file mode 100644 index de10b7ee8..000000000 --- a/src/test/java/com/google/api/core/ApiFuturesTest.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; - -public class ApiFuturesTest { - - @Test - public void testAddCallback() throws Exception { - final AtomicInteger flag = new AtomicInteger(); - SettableApiFuture future = SettableApiFuture.create(); - ApiFutures.addCallback( - future, - new ApiFutureCallback() { - @Override - public void onSuccess(Integer i) { - flag.set(i + 1); - } - - @Override - public void onFailure(Throwable t) { - flag.set(-1); - } - }, - directExecutor()); - future.set(0); - assertThat(flag.get()).isEqualTo(1); - } - - @Test - public void testCatch() throws Exception { - SettableApiFuture future = SettableApiFuture.create(); - ApiFuture fallback = - ApiFutures.catching( - future, - Exception.class, - new ApiFunction() { - @Override - public Integer apply(Exception ex) { - return 42; - } - }, - directExecutor()); - future.setException(new Exception()); - 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(); - ApiFuture transformedFuture = - ApiFutures.transform( - inputFuture, - new ApiFunction() { - @Override - public String apply(Integer input) { - return input.toString(); - } - }, - directExecutor()); - inputFuture.set(6); - assertThat(transformedFuture.get()).isEqualTo("6"); - } - - @Test - public void testTransformWithExecutor() throws Exception { - SettableApiFuture inputFuture = SettableApiFuture.create(); - final AtomicInteger counter = new AtomicInteger(0); - ApiFuture transformedFuture = - ApiFutures.transform( - inputFuture, - new ApiFunction() { - @Override - public String apply(Integer input) { - return input.toString(); - } - }, - new Executor() { - @Override - public void execute(Runnable command) { - counter.incrementAndGet(); - command.run(); - } - }); - inputFuture.set(6); - assertThat(transformedFuture.get()).isEqualTo("6"); - assertThat(counter.get()).isEqualTo(1); - } - - @Test - public void testAllAsList() throws Exception { - SettableApiFuture inputFuture1 = SettableApiFuture.create(); - SettableApiFuture inputFuture2 = SettableApiFuture.create(); - ApiFuture> listFuture = - ApiFutures.allAsList(ImmutableList.of(inputFuture1, inputFuture2)); - inputFuture1.set(1); - inputFuture2.set(2); - assertThat(listFuture.get()).containsExactly(1, 2).inOrder(); - } - - @Test - public void testTransformAsync() throws Exception { - ApiFuture inputFuture = ApiFutures.immediateFuture(0); - ApiFuture outputFuture = - ApiFutures.transformAsync( - inputFuture, - new ApiAsyncFunction() { - @Override - public ApiFuture apply(Integer input) { - return ApiFutures.immediateFuture(input + 1); - } - }, - directExecutor()); - assertThat(outputFuture.get()).isEqualTo(1); - } - - @Test - public void testTransformAsyncWithExecutor() throws Exception { - ApiFuture inputFuture = ApiFutures.immediateFuture(0); - final AtomicInteger counter = new AtomicInteger(0); - ApiFuture outputFuture = - ApiFutures.transformAsync( - inputFuture, - new ApiAsyncFunction() { - @Override - public ApiFuture apply(Integer input) { - return ApiFutures.immediateFuture(input + 1); - } - }, - new Executor() { - @Override - public void execute(Runnable command) { - counter.incrementAndGet(); - command.run(); - } - }); - assertThat(outputFuture.get()).isEqualTo(1); - assertThat(counter.get()).isEqualTo(1); - } - - @Test - public void testImmediateFailedFuture() throws InterruptedException { - ApiFuture future = - ApiFutures.immediateFailedFuture(new IllegalArgumentException("The message")); - IllegalArgumentException exception = null; - try { - future.get(); - } catch (ExecutionException e) { - exception = (IllegalArgumentException) e.getCause(); - } - assertThat(exception).isNotNull(); - assertThat(exception.getMessage()).isEqualTo("The message"); - } - - @Test - public void testImmediateCancelledFuture() throws InterruptedException, ExecutionException { - ApiFuture future = ApiFutures.immediateCancelledFuture(); - CancellationException exception = null; - try { - future.get(); - } catch (CancellationException e) { - exception = e; - } - assertThat(exception).isNotNull(); - } -} diff --git a/src/test/java/com/google/api/core/ApiServiceTest.java b/src/test/java/com/google/api/core/ApiServiceTest.java deleted file mode 100644 index a13b2d565..000000000 --- a/src/test/java/com/google/api/core/ApiServiceTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.util.concurrent.MoreExecutors; -import java.util.concurrent.atomic.AtomicReference; -import org.junit.Assert; -import org.junit.Test; - -public class ApiServiceTest { - @Test - public void testNoopService() { - ApiService service = - new AbstractApiService() { - @Override - protected void doStop() { - notifyStopped(); - } - - @Override - protected void doStart() { - notifyStarted(); - } - }; - service.startAsync().awaitRunning(); - Assert.assertTrue(service.isRunning()); - service.stopAsync().awaitTerminated(); - } - - @Test - public void testFailingService() { - final AtomicReference savedFailure = new AtomicReference<>(); - ApiService service = - new AbstractApiService() { - @Override - protected void doStop() { - // This should never be called. - throw new Error(); - } - - @Override - protected void doStart() { - notifyFailed(new IllegalStateException("this service always fails")); - } - }; - service.addListener( - new ApiService.Listener() { - @Override - public void failed(ApiService.State from, Throwable failure) { - savedFailure.set(failure); - } - }, - MoreExecutors.directExecutor()); - - try { - service.startAsync().awaitRunning(); - throw new RuntimeException("unreachable"); - } catch (IllegalStateException e) { - // Expected - } - - Assert.assertEquals(service.state(), ApiService.State.FAILED); - Assert.assertEquals(savedFailure.get().getMessage(), "this service always fails"); - Assert.assertEquals(service.failureCause().getMessage(), "this service always fails"); - } -} diff --git a/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java b/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java deleted file mode 100644 index 41c945c2e..000000000 --- a/src/test/java/com/google/api/core/ListenableFutureToApiFutureTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.truth.Truth; -import com.google.common.util.concurrent.SettableFuture; -import org.junit.Test; - -public class ListenableFutureToApiFutureTest { - - @Test - public void testGet() throws Exception { - SettableFuture future = SettableFuture.create(); - ListenableFutureToApiFuture apiFuture = new ListenableFutureToApiFuture<>(future); - future.set(3); - Truth.assertThat(apiFuture.get()).isEqualTo(3); - } -} diff --git a/src/test/java/com/google/api/core/SettableApiFutureTest.java b/src/test/java/com/google/api/core/SettableApiFutureTest.java deleted file mode 100644 index 6cfed9b92..000000000 --- a/src/test/java/com/google/api/core/SettableApiFutureTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.core; - -import com.google.common.truth.Truth; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Test; - -public class SettableApiFutureTest { - @Test - public void testSet() throws Exception { - SettableApiFuture future = SettableApiFuture.create(); - Truth.assertThat(future.isDone()).isFalse(); - future.set(42); - Truth.assertThat(future.get()).isEqualTo(42); - Truth.assertThat(future.get(1, TimeUnit.HOURS)).isEqualTo(42); - Truth.assertThat(future.isDone()).isTrue(); - } - - @Test - public void testCancel() throws Exception { - SettableApiFuture future = SettableApiFuture.create(); - Truth.assertThat(future.isDone()).isFalse(); - Truth.assertThat(future.isCancelled()).isFalse(); - future.cancel(false); - Truth.assertThat(future.isDone()).isTrue(); - Truth.assertThat(future.isCancelled()).isTrue(); - } - - @Test(expected = ExecutionException.class) - public void testException() throws Exception { - SettableApiFuture future = SettableApiFuture.create(); - future.setException(new Exception()); - future.get(); - } - - @Test - public void testListener() throws Exception { - final AtomicInteger flag = new AtomicInteger(); - SettableApiFuture future = SettableApiFuture.create(); - future.addListener( - new Runnable() { - @Override - public void run() { - flag.set(1); - } - }, - new Executor() { - @Override - public void execute(Runnable r) { - r.run(); - } - }); - future.set(0); - Truth.assertThat(flag.get()).isEqualTo(1); - } -} diff --git a/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java b/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java deleted file mode 100644 index 33b9033b8..000000000 --- a/src/test/java/com/google/api/pathtemplate/PathTemplateTest.java +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.pathtemplate; - -import com.google.common.collect.ImmutableMap; -import com.google.common.truth.Truth; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link PathTemplate}. */ -@RunWith(JUnit4.class) -public class PathTemplateTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - // Match - // ===== - - @Test - public void matchAtomicResourceName() { - PathTemplate template = PathTemplate.create("buckets/*/*/objects/*"); - assertPositionalMatch(template.match("buckets/f/o/objects/bar"), "f", "o", "bar"); - } - - @Test - public void matchTemplateWithUnboundedWildcard() { - PathTemplate template = PathTemplate.create("buckets/*/objects/**"); - assertPositionalMatch(template.match("buckets/foo/objects/bar/baz"), "foo", "bar/baz"); - } - - @Test - public void matchWithForcedHostName() { - PathTemplate template = PathTemplate.create("buckets/*/objects/*"); - Map match = template.matchFromFullName("somewhere.io/buckets/b/objects/o"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("somewhere.io"); - Truth.assertThat(match.get("$0")).isEqualTo("b"); - Truth.assertThat(match.get("$1")).isEqualTo("o"); - } - - @Test - public void matchWithHostName() { - PathTemplate template = PathTemplate.create("buckets/*/objects/*"); - Map match = template.match("//somewhere.io/buckets/b/objects/o"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("//somewhere.io"); - Truth.assertThat(match.get("$0")).isEqualTo("b"); - Truth.assertThat(match.get("$1")).isEqualTo("o"); - } - - @Test - public void matchWithHostNameAndProtocol() { - PathTemplate template = PathTemplate.create("projects/{project}/zones/{zone}"); - Map match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone")).isEqualTo("europe-west3-c"); - } - - @Test - public void matchWithHostNameAndProtocolWithTemplateStartWithBinding() { - PathTemplate template = PathTemplate.create("{project}/zones/{zone}"); - Map match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone")).isEqualTo("europe-west3-c"); - } - - @Test - public void pathWildcards_matchZeroOrMoreSegments() { - PathTemplate start = PathTemplate.create("{glob=**}/b"); - PathTemplate middle = PathTemplate.create("a/{glob=**}/b"); - PathTemplate end = PathTemplate.create("a/{glob=**}"); - - Truth.assertThat(start.match("b").get("glob")).isEmpty(); - Truth.assertThat(start.match("/b").get("glob")).isEmpty(); - Truth.assertThat(start.match("a/b").get("glob")).isEqualTo("a"); - Truth.assertThat(start.match("a/a/a/b").get("glob")).isEqualTo("a/a/a"); - - Truth.assertThat(middle.match("a/b").get("glob")).isEmpty(); - Truth.assertThat(middle.match("a//b").get("glob")).isEmpty(); - Truth.assertThat(middle.match("a/x/b").get("glob")).isEqualTo("x"); - Truth.assertThat(middle.match("a/x/y/z/b").get("glob")).isEqualTo("x/y/z"); - - Truth.assertThat(end.match("a").get("glob")).isEmpty(); - Truth.assertThat(end.match("a/").get("glob")).isEmpty(); - Truth.assertThat(end.match("a/b").get("glob")).isEqualTo("b"); - Truth.assertThat(end.match("a/b/b/b").get("glob")).isEqualTo("b/b/b"); - } - - @Test - public void pathWildcard_canMatchTheEmptyString() { - PathTemplate template = PathTemplate.create("{glob=**}"); - - Truth.assertThat(template.match("").get("glob")).isEmpty(); - Truth.assertThat(template.match("a").get("glob")).isEqualTo("a"); - Truth.assertThat(template.match("a/b").get("glob")).isEqualTo("a/b"); - } - - @Test - public void matchWithCustomMethod() { - PathTemplate template = PathTemplate.create("buckets/*/objects/*:custom"); - Map match = template.match("buckets/b/objects/o:custom"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("$0")).isEqualTo("b"); - Truth.assertThat(match.get("$1")).isEqualTo("o"); - } - - @Test - public void matchFailWhenPathMismatch() { - PathTemplate template = PathTemplate.create("buckets/*/*/objects/*"); - Truth.assertThat(template.match("buckets/f/o/o/objects/bar")).isNull(); - } - - @Test - public void matchFailWhenPathTooShort() { - PathTemplate template = PathTemplate.create("buckets/*/*/objects/*"); - Truth.assertThat(template.match("buckets/f/o/objects")).isNull(); - } - - @Test - public void matchFailWhenPathTooLong() { - PathTemplate template = PathTemplate.create("buckets/*/*/objects/*"); - Truth.assertThat(template.match("buckets/f/o/objects/too/long")).isNull(); - } - - @Test - public void matchWithUnboundInMiddle() { - PathTemplate template = PathTemplate.create("bar/**/foo/*"); - assertPositionalMatch(template.match("bar/foo/foo/foo/bar"), "foo/foo", "bar"); - } - - // Complex Resource ID Segments. - // ======== - - @Test - public void complexResourceIdBasicCases() { - // Separate by "~". - PathTemplate template = PathTemplate.create("projects/{project}/zones/{zone_a}~{zone_b}"); - Map match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c~us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a}~{zone_b")).isNull(); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - - // Separate by "-". - template = PathTemplate.create("projects/{project}/zones/{zone_a}-{zone_b}"); - match = template.match("projects/project-123/zones/europe-west3-c~us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe"); - Truth.assertThat(match.get("zone_b")).isEqualTo("west3-c~us-east3-a"); - - // Separate by ".". - template = PathTemplate.create("projects/{project}/zones/{zone_a}.{zone_b}"); - match = template.match("projects/project-123/zones/europe-west3-c.us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - - // Separate by "_". - template = PathTemplate.create("projects/{project}/zones/{zone_a}_{zone_b}"); - match = template.match("projects/project-123/zones/europe-west3-c_us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - } - - @Test - public void complexResourceIdEqualsWildcard() { - PathTemplate template = PathTemplate.create("projects/{project=*}/zones/{zone_a=*}~{zone_b=*}"); - Map match = - template.match("projects/project-123/zones/europe-west3-c~us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a}~{zone_b")).isNull(); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - } - - @Test - public void complexResourceIdEqualsPathWildcard() { - thrown.expect(ValidationException.class); - PathTemplate template = PathTemplate.create("projects/{project=*}/zones/{zone_a=**}~{zone_b}"); - thrown.expectMessage( - String.format( - "parse error: wildcard path not allowed in complex ID resource '%s'", "zone_a")); - - template = PathTemplate.create("projects/{project=*}/zones/{zone_a}.{zone_b=**}"); - thrown.expectMessage( - String.format( - "parse error: wildcard path not allowed in complex ID resource '%s'", "zone_b")); - } - - @Test - public void complexResourceIdMissingMatches() { - PathTemplate template = PathTemplate.create("projects/{project}/zones/{zone_a}~{zone_b}"); - Truth.assertThat(template.match("projects/project-123/zones/europe-west3-c")).isNull(); - - template = PathTemplate.create("projects/{project}/zones/{zone_a}~{zone_b}.{zone_c}"); - Map match = - template.match("projects/project-123/zones/europe-west3-c~.us-east3-a"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a}~{zone_b")).isNull(); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEmpty(); - Truth.assertThat(match.get("zone_c")).isEqualTo("us-east3-a"); - } - - @Test - public void complexResourceIdNoSeparator() { - thrown.expect(ValidationException.class); - PathTemplate.create("projects/{project}/zones/{zone_a}{zone_b}"); - thrown.expectMessage( - String.format( - "parse error: missing or 2+ consecutive delimiter characters in '%s'", - "{zone_a}{zone_b}")); - - PathTemplate.create("projects/{project}/zones/{zone_a}_{zone_b}{zone_c}"); - thrown.expectMessage( - String.format( - "parse error: missing or 2+ consecutive delimiter characters in '%s'", - "{zone_a}_{zone_b}{zone_c}")); - } - - @Test - public void complexResourceIdInvalidDelimiter() { - thrown.expect(ValidationException.class); - // Not a comprehensive set of invalid delimiters, please check the class's defined pattern. - List someInvalidDelimiters = - new ArrayList<>(Arrays.asList("|", "!", "@", "a", "1", ",", "{", ")")); - for (String invalidDelimiter : someInvalidDelimiters) { - PathTemplate.create( - String.format("projects/{project=*}/zones/{zone_a}%s{zone_b}", invalidDelimiter)); - thrown.expectMessage( - String.format( - "parse error: invalid complex resource ID delimiter character in '%s'", - String.format("{zone_a}%s{zone_b}", invalidDelimiter))); - } - } - - @Test - public void complexResourceIdMixedSeparators() { - // Separate by a mix of delimiters. - PathTemplate template = - PathTemplate.create("projects/{project}/zones/{zone_a}~{zone_b}.{zone_c}-{zone_d}"); - Map match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c~us-east3-a.us-west2-b-europe-west2-b"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - Truth.assertThat(match.get("zone_c")).isEqualTo("us"); - Truth.assertThat(match.get("zone_d")).isEqualTo("west2-b-europe-west2-b"); - - template = PathTemplate.create("projects/{project}/zones/{zone_a}.{zone_b}.{zone_c}~{zone_d}"); - match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c.us-east3-a.us-west2-b~europe-west2-b"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe-west3-c"); - Truth.assertThat(match.get("zone_b")).isEqualTo("us-east3-a"); - Truth.assertThat(match.get("zone_c")).isEqualTo("us-west2-b"); - Truth.assertThat(match.get("zone_d")).isEqualTo("europe-west2-b"); - } - - @Test - public void complexResourceIdInParent() { - // One parent has a complex resource ID. - PathTemplate template = - PathTemplate.create( - "projects/{project}/zones/{zone_a}-{zone_b}_{zone_c}/machines/{machine}"); - Map match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project-123/zones/europe-west3-c-us-east3-a_us-west2-b/machines/roomba"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("project")).isEqualTo("project-123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe"); - Truth.assertThat(match.get("zone_b")).isEqualTo("west3-c-us-east3-a"); - Truth.assertThat(match.get("zone_c")).isEqualTo("us-west2-b"); - Truth.assertThat(match.get("machine")).isEqualTo("roomba"); - - // All parents and resource IDs have complex resource IDs. - template = - PathTemplate.create( - "projects/{foo}_{bar}/zones/{zone_a}-{zone_b}_{zone_c}/machines/{cell1}.{cell2}"); - match = - template.match( - "https://www.googleapis.com/compute/v1/projects/project_123/zones/europe-west3-c-us-east3-a_us-west2-b/machines/roomba.broomba"); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get(PathTemplate.HOSTNAME_VAR)).isEqualTo("https://www.googleapis.com"); - Truth.assertThat(match.get("foo")).isEqualTo("project"); - Truth.assertThat(match.get("bar")).isEqualTo("123"); - Truth.assertThat(match.get("zone_a")).isEqualTo("europe"); - Truth.assertThat(match.get("zone_b")).isEqualTo("west3-c-us-east3-a"); - Truth.assertThat(match.get("zone_c")).isEqualTo("us-west2-b"); - Truth.assertThat(match.get("cell1")).isEqualTo("roomba"); - Truth.assertThat(match.get("cell2")).isEqualTo("broomba"); - } - - @Test - public void complexResourceBasicInvalidIds() { - thrown.expect(ValidationException.class); - PathTemplate.create("projects/*/zones/~{zone_a}"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "~{zone_a}")); - - PathTemplate.create("projects/*/zones/{zone_a}~"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "{zone_a}~")); - - PathTemplate.create("projects/*/zones/.{zone_a}"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", ".{zone_a}")); - - PathTemplate.create("projects/*/zones/{zone_a}."); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "{zone_a}.")); - - PathTemplate.create("projects/*/zones/-{zone_a}"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "-{zone_a}")); - - PathTemplate.create("projects/*/zones/{zone_a}-"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "{zone_a}-")); - - PathTemplate.create("projects/*/zones/_{zone_a}"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "{zone_a}_")); - - PathTemplate.create("projects/*/zones/{zone_a}_"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", "{zone_a}_")); - } - - @Test - public void complexResourceMultipleDelimiters() { - thrown.expect(ValidationException.class); - PathTemplate.create("projects/*/zones/.-~{zone_a}"); - thrown.expectMessage( - String.format("parse error: invalid begin or end character in '%s'", ".-~{zone_a}")); - - PathTemplate.create("projects/*/zones/{zone_a}~.{zone_b}"); - thrown.expectMessage( - String.format( - "parse error: missing or 2+ consecutive delimiter characters in '%s'", - "{zone_a}~.{zone_b}")); - - PathTemplate.create("projects/*/zones/{zone_a}~{zone_b}..{zone_c}"); - thrown.expectMessage( - String.format( - "parse error: missing or 2+ consecutive delimiter characters in '%s'", - "{zone_a}~{zone_b}..{zone_c}")); - - String pathString = "projects/project_123/zones/lorum~ipsum"; - PathTemplate template = PathTemplate.create("projects/*/zones/{zone_.~-a}~{zone_b}"); - template.validate(pathString, ""); - // No assertion - success is no exception thrown from template.validate(). - Map match = template.match(pathString); - Truth.assertThat(match).isNotNull(); - Truth.assertThat(match.get("zone_.~-a")).isEqualTo("lorum"); - Truth.assertThat(match.get("zone_b")).isEqualTo("ipsum"); - } - - // Validate - // ======== - - @Test - public void validateSuccess() { - String templateString = "buckets/*/objects/*"; - String pathString = "buckets/bucket/objects/object"; - PathTemplate template = PathTemplate.create(templateString); - template.validate(pathString, ""); - // No assertion - success is no exception thrown from template.validate - } - - @Test - public void validateFailure() { - thrown.expect(ValidationException.class); - String templateString = "buckets/*/objects/*"; - String pathString = "buckets/bucket/invalid/object"; - thrown.expectMessage( - String.format("Parameter \"%s\" must be in the form \"%s\"", pathString, templateString)); - PathTemplate template = PathTemplate.create(templateString); - template.validate(pathString, ""); - } - - @Test - public void validateMatchSuccess() { - String templateString = "buckets/*/objects/{object_id}"; - String pathString = "buckets/bucket/objects/object"; - PathTemplate template = PathTemplate.create(templateString); - Map matchMap = template.validatedMatch(pathString, ""); - Truth.assertThat(matchMap.get("$0")).isEqualTo("bucket"); - Truth.assertThat(matchMap.get("object_id")).isEqualTo("object"); - } - - @Test - public void validateMatchFailure() { - thrown.expect(ValidationException.class); - String templateString = "buckets/*/objects/*"; - String pathString = "buckets/bucket/invalid/object"; - thrown.expectMessage( - String.format("Parameter \"%s\" must be in the form \"%s\"", pathString, templateString)); - PathTemplate template = PathTemplate.create(templateString); - template.validatedMatch(pathString, ""); - } - - // Instantiate - // =========== - - @Test - public void instantiateAtomicResource() { - PathTemplate template = PathTemplate.create("buckets/*/*/*/objects/*"); - String url = template.instantiate("$0", "f", "$1", "o", "$2", "o", "$3", "bar"); - Truth.assertThat(url).isEqualTo("buckets/f/o/o/objects/bar"); - } - - @Test - public void instantiateEscapeUnsafeChar() { - PathTemplate template = PathTemplate.create("buckets/*/objects/*"); - Truth.assertThat(template.instantiate("$0", "f/o/o", "$1", "b/a/r")) - .isEqualTo("buckets/f%2Fo%2Fo/objects/b%2Fa%2Fr"); - } - - @Test - public void instantiateNotEscapeForUnboundedWildcard() { - PathTemplate template = PathTemplate.create("buckets/*/objects/**"); - Truth.assertThat(template.instantiate("$0", "f/o/o", "$1", "b/a/r")) - .isEqualTo("buckets/f%2Fo%2Fo/objects/b/a/r"); - } - - @Test - public void instantiateFailWhenTooFewVariables() { - thrown.expect(ValidationException.class); - PathTemplate template = PathTemplate.create("buckets/*/*/*/objects/*"); - template.instantiate("$0", "f", "1", "o"); - } - - @Test - public void instantiateWithUnboundInMiddle() { - PathTemplate template = PathTemplate.create("bar/**/foo/*"); - Truth.assertThat(template.instantiate("$0", "1/2", "$1", "3")).isEqualTo("bar/1/2/foo/3"); - } - - @Test - public void instantiatePartial() { - PathTemplate template = PathTemplate.create("bar/*/foo/*"); - String instance = template.instantiatePartial(ImmutableMap.of("$0", "_1")); - Truth.assertThat(instance).isEqualTo("bar/_1/foo/*"); - } - - @Test - public void instantiateWithHostName() { - PathTemplate template = PathTemplate.create("bar/*"); - String instance = - template.instantiate( - ImmutableMap.of(PathTemplate.HOSTNAME_VAR, "//somewhere.io", "$0", "foo")); - Truth.assertThat(instance).isEqualTo("//somewhere.io/bar/foo"); - } - - @Test - public void instantiateEscapeUnsafeCharNoEncoding() { - thrown.expect(ValidationException.class); - thrown.expectMessage("Invalid character \"/\" in path section \"f/o/o\"."); - PathTemplate template = PathTemplate.createWithoutUrlEncoding("buckets/*/objects/*"); - template.instantiate("$0", "f/o/o", "$1", "b/a/r"); - } - - @Test - public void instantiateNotEscapeForUnboundedWildcardNoEncoding() { - PathTemplate template = PathTemplate.createWithoutUrlEncoding("buckets/*/objects/**"); - Truth.assertThat(template.instantiate("$0", "foo", "$1", "b/a/r")) - .isEqualTo("buckets/foo/objects/b/a/r"); - } - - @Test - public void instantiateWithGoogProject() { - PathTemplate template = PathTemplate.create("projects/{project}"); - String instance = template.instantiate(ImmutableMap.of("project", "google.com:test-proj")); - Truth.assertThat(instance).isEqualTo("projects/google.com%3Atest-proj"); - } - - @Test - public void instantiateWithGoogProjectNoEncoding() { - PathTemplate template = PathTemplate.createWithoutUrlEncoding("projects/{project}"); - String instance = template.instantiate(ImmutableMap.of("project", "google.com:test-proj")); - Truth.assertThat(instance).isEqualTo("projects/google.com:test-proj"); - } - - @Test - public void instantiateWithUnusualCharactersNoEncoding() { - PathTemplate template = PathTemplate.createWithoutUrlEncoding("bar/*"); - String instance = template.instantiate(ImmutableMap.of("$0", "asdf:;`~,.<>[]!@#$%^&*()")); - Truth.assertThat(instance).isEqualTo("bar/asdf:;`~,.<>[]!@#$%^&*()"); - } - - // Other - // ===== - - @Test - public void testMultiplePathWildcardFailure() { - thrown.expect(IllegalArgumentException.class); - PathTemplate.create("bar/**/{name=foo/**}:verb"); - } - - @Test - public void testTemplateWithSimpleBinding() { - PathTemplate template = PathTemplate.create("/v1/messages/{message_id}"); - String url = template.instantiate("message_id", "mymessage"); - Truth.assertThat(url).isEqualTo("v1/messages/mymessage"); - } - - @Test - public void testTemplateWithMultipleSimpleBindings() { - PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}"); - String url = template.instantiate("shelf", "s1", "book", "b1"); - Truth.assertThat(url).isEqualTo("v1/shelves/s1/books/b1"); - } - - private static void assertPositionalMatch(Map match, String... expected) { - Truth.assertThat(match).isNotNull(); - int i = 0; - for (; i < expected.length; ++i) { - Truth.assertThat(expected[i]).isEqualTo(match.get("$" + i)); - } - Truth.assertThat(i).isEqualTo(match.size()); - } -} diff --git a/src/test/java/com/google/api/pathtemplate/TemplatedResourceNameTest.java b/src/test/java/com/google/api/pathtemplate/TemplatedResourceNameTest.java deleted file mode 100644 index 77e5244a1..000000000 --- a/src/test/java/com/google/api/pathtemplate/TemplatedResourceNameTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.google.api.pathtemplate; - -import com.google.common.truth.Truth; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Tests for {@link TemplatedResourceName}. As resource names are mostly a wrapper around path - * templates, not much needs to be done here. - */ -@RunWith(JUnit4.class) -public class TemplatedResourceNameTest { - - @Test - public void resourceNameMethods() { - PathTemplate template = PathTemplate.create("buckets/*/objects/**"); - TemplatedResourceName name = TemplatedResourceName.create(template, "buckets/b/objects/1/2"); - Truth.assertThat(name.toString()).isEqualTo("buckets/b/objects/1/2"); - Truth.assertThat(name.get("$1")).isEqualTo("1/2"); - Truth.assertThat(name.get("$0")).isEqualTo("b"); - Truth.assertThat(name.parentName().toString()).isEqualTo("buckets/b/objects"); - } -} diff --git a/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java b/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java deleted file mode 100644 index ab13287ea..000000000 --- a/src/test/java/com/google/api/resourcenames/UntypedResourceNameTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2018, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.google.api.resourcenames; - -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Tests for {@link UntypedResourceNameTest}. - */ -@RunWith(JUnit4.class) -public class UntypedResourceNameTest { - private static final String NAME_STRING = "sunshine"; - private static final String EMPTY_STRING = ""; - - @Test - public void testGetFieldValues() { - assertTrue(UntypedResourceName.isParsableFrom(NAME_STRING)); - UntypedResourceName fooName = UntypedResourceName.parse(NAME_STRING); - - Map fieldValuesMap = fooName.getFieldValuesMap(); - assertTrue(fieldValuesMap.containsKey(EMPTY_STRING)); - assertEquals(NAME_STRING, fieldValuesMap.get(EMPTY_STRING)); - assertEquals(1, fieldValuesMap.size()); - assertEquals(null, fieldValuesMap.get(NAME_STRING)); - } - - @Test - public void testInsertIntoFieldValuesMap() { - UntypedResourceName fooName = UntypedResourceName.parse(NAME_STRING); - Map fieldValuesMap = fooName.getFieldValuesMap(); - - try { - fieldValuesMap.put(EMPTY_STRING, "foo"); - fail("fieldValuesMap should prevent insertion into internal map. "); - } catch (UnsupportedOperationException e) { - } - - try { - fieldValuesMap.put(null, "foo"); - fail("fieldValuesMap should prevent insertion into internal map. "); - } catch (UnsupportedOperationException e) { - } - - try { - fieldValuesMap.put(NAME_STRING, NAME_STRING); - fail("fieldValuesMap should prevent insertion into internal map. "); - } catch (UnsupportedOperationException e) { - } - } - - @Test - public void testNullName() { - assertFalse(UntypedResourceName.isParsableFrom(null)); - try { - UntypedResourceName fooName = UntypedResourceName.parse(null); - } catch (NullPointerException e) { - } - } -} diff --git a/templates/apidocs_index.html.template b/templates/apidocs_index.html.template deleted file mode 100644 index 66505a09f..000000000 --- a/templates/apidocs_index.html.template +++ /dev/null @@ -1 +0,0 @@ - diff --git a/version.txt b/version.txt deleted file mode 100644 index 9ab8337f3..000000000 --- a/version.txt +++ /dev/null @@ -1 +0,0 @@ -1.9.1