diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 5db36a5f7..359fe71c1 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,5 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e -# created: 2024-05-09T16:31:37.168667071Z + digest: sha256:72f0d373307d128b2cb720c5cb4d90b31f0e86529dd138c632710ae0c69efae3 +# created: 2024-06-05T18:32:21.724930324Z diff --git a/.github/release-please.yml b/.github/release-please.yml index eb0e905a5..b1900aa11 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -22,3 +22,7 @@ branches: handleGHRelease: true releaseType: java-backport branch: 1.43.x + - bumpMinorPreMajor: true + handleGHRelease: true + releaseType: java-backport + branch: 1.44.x diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 3faf69390..5f2262e8a 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -84,6 +84,20 @@ branchProtectionRules: - dependencies (11) - clirr - cla/google + - pattern: 1.44.x + isAdminEnforced: true + requiredApprovingReviewCount: 1 + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: false + requiredStatusCheckContexts: + - units (7) + - units (8) + - units (11) + - windows + - dependencies (8) + - dependencies (11) + - clirr + - cla/google permissionRules: - team: yoshi-admins permission: admin diff --git a/.github/trusted-contribution.yml b/.github/trusted-contribution.yml index a0ba1f7d9..88d3ac9bf 100644 --- a/.github/trusted-contribution.yml +++ b/.github/trusted-contribution.yml @@ -1,3 +1,9 @@ trustedContributors: - renovate-bot - gcf-owl-bot[bot] + +annotations: +- type: comment + text: "/gcbrun" +- type: label + text: "kokoro:force-run" diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml index 7a106d007..18d92e5a2 100644 --- a/.github/workflows/auto-release.yaml +++ b/.github/workflows/auto-release.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.head_ref, 'release-please') steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true diff --git a/.github/workflows/ci-java7.yaml b/.github/workflows/ci-java7.yaml index 2c8257d45..5086c87d5 100644 --- a/.github/workflows/ci-java7.yaml +++ b/.github/workflows/ci-java7.yaml @@ -24,20 +24,21 @@ jobs: name: "units (7)" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 # setup-java v2 or higher does not have version 1.7 with: - version: 1.7 + java-version: 7 + distribution: zulu architecture: x64 - run: | java -version # This value is used in "-Djvm=" later echo "JAVA7_HOME=${JAVA_HOME}" >> $GITHUB_ENV - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: java-version: 17 - distribution: temurin + distribution: zulu - name: Set up Maven uses: stCarolas/setup-maven@v4.5 with: @@ -55,7 +56,7 @@ jobs: # dailymotion-simple-cmdline-sample and google-http-client-assembly depend on # google-http-client-jackson2 mvn --batch-mode --show-version -ntp test \ - --projects '!google-http-client-jackson2,!google-http-client-appengine,!samples/dailymotion-simple-cmdline-sample,!google-http-client-assembly' \ + --projects '!google-http-client-jackson2,!google-http-client-appengine,!samples/dailymotion-simple-cmdline-sample,!google-http-client-assembly,!google-http-client-apache-v5' \ -Dclirr.skip=true -Denforcer.skip=true -Dmaven.javadoc.skip=true \ -Dgcloud.download.skip=true -T 1C \ -Dproject.surefire.version=2.22.2 \ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 32feef7d1..4595806ea 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,8 +27,8 @@ jobs: matrix: java: [8, 11, 17] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{matrix.java}} @@ -41,8 +41,8 @@ jobs: steps: - name: Support longpaths run: git config --system core.longpaths true - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 @@ -56,8 +56,8 @@ jobs: matrix: java: [8, 11, 17] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{matrix.java}} @@ -66,8 +66,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 @@ -78,8 +78,8 @@ jobs: clirr: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 @@ -94,8 +94,8 @@ jobs: name: "units (21)" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: java-version: 21 distribution: temurin @@ -104,7 +104,7 @@ jobs: # https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java" >> $GITHUB_ENV shell: bash - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: java-version: 8 distribution: temurin diff --git a/.github/workflows/downstream.yaml b/.github/workflows/downstream.yaml index c4be85eaa..1f44d518d 100644 --- a/.github/workflows/downstream.yaml +++ b/.github/workflows/downstream.yaml @@ -133,8 +133,8 @@ jobs: - workflow-executions - workflows steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: zulu java-version: ${{matrix.java}} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 7dd91434a..f153dddd4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,12 +32,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: SARIF file path: results.sarif @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + uses: github/codeql-action/upload-sarif@883d8588e56d1753a8a58c1c86e88976f0c23449 # v3.26.3 with: sarif_file: results.sarif diff --git a/.kokoro/presubmit/graalvm-native-a.cfg b/.kokoro/presubmit/graalvm-native-a.cfg index 0b14fb23d..54dca4f2c 100644 --- a/.kokoro/presubmit/graalvm-native-a.cfg +++ b/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_a:1.7.6" + value: "gcr.io/cloud-devrel-public-resources/graalvm_a:1.11.0" } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-b.cfg b/.kokoro/presubmit/graalvm-native-b.cfg index 799c80594..8b05c77ff 100644 --- a/.kokoro/presubmit/graalvm-native-b.cfg +++ b/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_b:1.7.6" + value: "gcr.io/cloud-devrel-public-resources/graalvm_b:1.11.0" } env_vars: { @@ -30,4 +30,4 @@ env_vars: { env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb4c04d2..3dcf93689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [1.45.0](https://github.com/googleapis/google-http-java-client/compare/v1.44.2...v1.45.0) (2024-08-21) + + +### Features + +* Introduce google-http-client-apache-v5 (Apache Client/Core 5.x) ([#1960](https://github.com/googleapis/google-http-java-client/issues/1960)) ([5d527dc](https://github.com/googleapis/google-http-java-client/commit/5d527dc3afade0834a82e5280f22e0129b5f1297)) +* Next release from main is 1.45.0 ([#1972](https://github.com/googleapis/google-http-java-client/issues/1972)) ([094dcc8](https://github.com/googleapis/google-http-java-client/commit/094dcc87f22d16686242ce6cb06151b2a199ec2a)) + + +### Dependencies + +* Update actions/checkout action to v4 ([#1993](https://github.com/googleapis/google-http-java-client/issues/1993)) ([f8b0cc1](https://github.com/googleapis/google-http-java-client/commit/f8b0cc1c908b4ebdf3c30a9f9a9b50c96d33f781)) +* Update actions/github-script action to v7 ([#1994](https://github.com/googleapis/google-http-java-client/issues/1994)) ([e527f0d](https://github.com/googleapis/google-http-java-client/commit/e527f0d9624e47c37a551590cf555f6207751fe9)) +* Update actions/setup-java action to v4 ([#1995](https://github.com/googleapis/google-http-java-client/issues/1995)) ([07aa01c](https://github.com/googleapis/google-http-java-client/commit/07aa01c2f86dc35fd6d1f968cbf111315ef26aa5)) +* Update actions/upload-artifact action to v4 ([#1996](https://github.com/googleapis/google-http-java-client/issues/1996)) ([5ba7021](https://github.com/googleapis/google-http-java-client/commit/5ba70218d8bdae18094b1031f9c800688aa58fb4)) +* Update dependency com.fasterxml.jackson.core:jackson-core to v2.17.2 ([#1987](https://github.com/googleapis/google-http-java-client/issues/1987)) ([4202d32](https://github.com/googleapis/google-http-java-client/commit/4202d328ea2cefff0771036b010fbfd80928f88c)) +* Update dependency com.google.cloud:native-image-shared-config to v1.7.7 ([#1937](https://github.com/googleapis/google-http-java-client/issues/1937)) ([b224a1d](https://github.com/googleapis/google-http-java-client/commit/b224a1d64cae44878f1bb0af83fb8e33e2e12d63)) +* Update dependency com.google.cloud:native-image-shared-config to v1.9.0 ([#1961](https://github.com/googleapis/google-http-java-client/issues/1961)) ([792e44f](https://github.com/googleapis/google-http-java-client/commit/792e44f6a2b7678fef30c3bdfc0955be533a7613)) +* Update dependency com.google.code.gson:gson to v2.11.0 ([#1988](https://github.com/googleapis/google-http-java-client/issues/1988)) ([63afd35](https://github.com/googleapis/google-http-java-client/commit/63afd35f0a3c15f5a66f5b6a06bae01f82b54504)) +* Update dependency com.google.errorprone:error_prone_annotations to v2.30.0 ([#1989](https://github.com/googleapis/google-http-java-client/issues/1989)) ([6e19c5c](https://github.com/googleapis/google-http-java-client/commit/6e19c5ca66c67dad53272998535ed197559dfe02)) +* Update dependency com.google.j2objc:j2objc-annotations to v3 ([#1998](https://github.com/googleapis/google-http-java-client/issues/1998)) ([3d70537](https://github.com/googleapis/google-http-java-client/commit/3d7053747076e599f819c41f8362f6070a96ce8a)) +* Update dependency io.grpc:grpc-context to v1.66.0 ([#1990](https://github.com/googleapis/google-http-java-client/issues/1990)) ([66a9f15](https://github.com/googleapis/google-http-java-client/commit/66a9f15c35bc64c25f10094c424e025ea6b0a693)) +* Update dependency org.apache.httpcomponents.core5:httpcore5 to v5.2.5 ([#2002](https://github.com/googleapis/google-http-java-client/issues/2002)) ([8c61065](https://github.com/googleapis/google-http-java-client/commit/8c6106505a119380e555c64151542445f0e1a5f8)) +* Update github/codeql-action action to v3 ([#2000](https://github.com/googleapis/google-http-java-client/issues/2000)) ([7250f64](https://github.com/googleapis/google-http-java-client/commit/7250f649be7a989dc0a855d6f6ddff987ac0ebaa)) +* Update ossf/scorecard-action action to v2.4.0 ([#1992](https://github.com/googleapis/google-http-java-client/issues/1992)) ([08c5e5a](https://github.com/googleapis/google-http-java-client/commit/08c5e5a7f7a887aaccc03a40c784d34ecbc45984)) +* Update project.appengine.version to v2.0.27 ([#1938](https://github.com/googleapis/google-http-java-client/issues/1938)) ([3f27cc8](https://github.com/googleapis/google-http-java-client/commit/3f27cc800db62c2208160234a5afad641f1a3781)) +* Update project.appengine.version to v2.0.29 ([#1978](https://github.com/googleapis/google-http-java-client/issues/1978)) ([a3fd1e3](https://github.com/googleapis/google-http-java-client/commit/a3fd1e34925a531d47613145d5f3b5473cef2d82)) + ## [1.44.2](https://github.com/googleapis/google-http-java-client/compare/v1.44.1...v1.44.2) (2024-05-16) diff --git a/docs/http-transport.md b/docs/http-transport.md index 0167db4ac..b6d94cce2 100644 --- a/docs/http-transport.md +++ b/docs/http-transport.md @@ -19,8 +19,12 @@ There are three built-in low-level HTTP transports: 1. [`NetHttpTransport`][net-http-transport]: based on [`HttpURLConnection`][http-url-connection] that is found in all Java SDKs, and thus usually the simplest choice. +1. [`Apache5HttpTransport`][apache-http-transport]: based on the popular + [Apache 5.x HttpClient][apache5-http-client] that allows for more customization. 1. [`ApacheHttpTransport`][apache-http-transport]: based on the popular -[Apache HttpClient][apache-http-client] that allows for more customization. +[Apache 4.x HttpClient][apache-http-client] that allows for more customization. Note that this transport implementation +relies on [Apache 4.x HttpCore][apache-http-core] which has reached end of life. It is recommended to use +[`Apache5HttpTransport`][apache-http-transport] instead. 1. [`UrlFetchTransport`][url-fetch-transport]: based on the [URL Fetch Java API][url-fetch] in the Google App Engine SDK. @@ -124,7 +128,10 @@ HttpRequestFactory requestFactory = transport.createRequestFactory(new MyInitial [net-http-transport]: https://googleapis.dev/java/google-http-client/latest/index.html?com/google/api/client/http/javanet/NetHttpTransport.html [http-url-connection]: http://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html [apache-http-transport]: https://googleapis.dev/java/google-http-client/latest/index.html?com/google/api/client/http/apache/v2/ApacheHttpTransport.html -[apache-http-client]: http://hc.apache.org/httpcomponents-client-ga/index.html +[apache5-http-transport]: https://github.com/googleapis/google-http-java-client/blob/de8743587d1415e8a6046096ac1fc0a5e81490c3/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpTransport.java +[apache-http-client]: https://hc.apache.org/httpcomponents-client-4.5.x/index.html +[apache-http-core]: https://hc.apache.org/httpcomponents-core-4.4.x/index.html +[apache5-http-client]: https://hc.apache.org/httpcomponents-client-5.3.x/index.html [url-fetch-transport]: https://googleapis.dev/java/google-http-client/latest/index.html?com/google/api/client/extensions/appengine/http/UrlFetchTransport.html [url-fetch]: https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/urlfetch/package-summary [logger]: https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html diff --git a/google-http-client-android-test/pom.xml b/google-http-client-android-test/pom.xml index 372af1f53..48bc0f333 100644 --- a/google-http-client-android-test/pom.xml +++ b/google-http-client-android-test/pom.xml @@ -4,7 +4,7 @@ google-http-client google-http-client-android-test Test project for google-http-client-android. - 1.44.2 + 1.45.0 apk @@ -53,7 +53,7 @@ com.google.http-client google-http-client-android - 1.44.2 + 1.45.0 android @@ -72,7 +72,7 @@ com.google.http-client google-http-client-test - 1.44.2 + 1.45.0 junit diff --git a/google-http-client-android/pom.xml b/google-http-client-android/pom.xml index fadc64cb6..1ac9f5e2b 100644 --- a/google-http-client-android/pom.xml +++ b/google-http-client-android/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-android - 1.44.2 + 1.45.0 Android Platform Extensions to the Google HTTP Client Library for Java. diff --git a/google-http-client-apache-v2/pom.xml b/google-http-client-apache-v2/pom.xml index 55676873b..0e1c72742 100644 --- a/google-http-client-apache-v2/pom.xml +++ b/google-http-client-apache-v2/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-apache-v2 - 1.44.2 + 1.45.0 Apache HTTP transport v2 for the Google HTTP Client Library for Java. @@ -29,7 +29,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-test-source diff --git a/google-http-client-apache-v5/pom.xml b/google-http-client-apache-v5/pom.xml new file mode 100644 index 000000000..c2cd4f070 --- /dev/null +++ b/google-http-client-apache-v5/pom.xml @@ -0,0 +1,116 @@ + + 4.0.0 + + com.google.http-client + google-http-client-parent + 1.45.0 + ../pom.xml + + google-http-client-apache-v5 + 1.45.0 + Apache HTTP transport v5 for the Google HTTP Client Library for Java. + + + + + maven-javadoc-plugin + + + https://download.oracle.com/javase/7/docs/api/ + + ${project.name} ${project.version} + ${project.artifactId} ${project.version} + + + + maven-source-plugin + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + add-test-source + generate-test-sources + + add-test-source + + + + target/generated-test-sources + + + + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + com.google.api.client.http.apache.v5 + + + + + + org.apache.felix + maven-bundle-plugin + 5.1.9 + + + bundle-manifest + process-classes + + manifest + + + + + + maven-compiler-plugin + 3.13.0 + + 1.8 + 1.8 + + + + + + + com.google.http-client + google-http-client + + + org.apache.httpcomponents + httpcore + + + org.apache.httpcomponents + httpclient + + + + + com.google.guava + guava + + + org.apache.httpcomponents.client5 + httpclient5 + + + org.apache.httpcomponents.core5 + httpcore5 + + + junit + junit + test + + + diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ContentEntity.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ContentEntity.java new file mode 100644 index 000000000..4a5ab84e6 --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ContentEntity.java @@ -0,0 +1,79 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import com.google.api.client.util.Preconditions; +import com.google.api.client.util.StreamingContent; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.hc.core5.http.io.entity.AbstractHttpEntity; + +/** + * Translation class to make google-http-client entity conform with Apache 5.x {@link + * AbstractHttpEntity} + */ +final class Apache5ContentEntity extends AbstractHttpEntity { + + /** Content length or less than zero if not known. */ + private final long contentLength; + + /** Streaming content. */ + private final StreamingContent streamingContent; + + /** + * @param contentLength content length or less than zero if not known + * @param streamingContent streaming content + */ + Apache5ContentEntity( + long contentLength, + StreamingContent streamingContent, + String contentType, + String contentEncoding) { + super(contentType, contentEncoding, contentLength == -1); + this.contentLength = contentLength; + this.streamingContent = Preconditions.checkNotNull(streamingContent); + } + + @Override + public InputStream getContent() { + throw new UnsupportedOperationException(); + } + + @Override + public long getContentLength() { + return contentLength; + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public boolean isStreaming() { + return true; + } + + @Override + public void writeTo(OutputStream out) throws IOException { + if (contentLength != 0) { + streamingContent.writeTo(out); + } + } + + @Override + public void close() throws IOException {} +} diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpRequest.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpRequest.java new file mode 100644 index 000000000..99d6eca8e --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpRequest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import com.google.api.client.http.LowLevelHttpRequest; +import com.google.api.client.http.LowLevelHttpResponse; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.routing.RoutingSupport; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.util.Timeout; + +public final class Apache5HttpRequest extends LowLevelHttpRequest { + + private final HttpUriRequestBase request; + + private final RequestConfig.Builder requestConfig; + + private final HttpClient httpClient; + + Apache5HttpRequest(HttpClient httpClient, HttpUriRequestBase request) { + this.httpClient = httpClient; + this.request = request; + // disable redirects as google-http-client handles redirects + this.requestConfig = RequestConfig.custom().setRedirectsEnabled(false); + } + + @Override + public void addHeader(String name, String value) { + request.addHeader(name, value); + } + + @Override + public void setTimeout(int connectTimeout, int readTimeout) throws IOException { + requestConfig + .setConnectTimeout(Timeout.of(connectTimeout, TimeUnit.MILLISECONDS)) + // ResponseTimeout behaves the same as 4.x's SocketTimeout + .setResponseTimeout(Timeout.of(readTimeout, TimeUnit.MILLISECONDS)); + } + + @Override + public LowLevelHttpResponse execute() throws IOException { + if (getStreamingContent() != null) { + Apache5ContentEntity entity = + new Apache5ContentEntity( + getContentLength(), getStreamingContent(), getContentType(), getContentEncoding()); + request.setEntity(entity); + } + request.setConfig(requestConfig.build()); + HttpHost target; + try { + target = RoutingSupport.determineHost(request); + } catch (HttpException e) { + throw new ClientProtocolException("The request's host is invalid.", e); + } + // we use a null context so the client creates the default one internally + ClassicHttpResponse httpResponse = httpClient.executeOpen(target, request, null); + return new Apache5HttpResponse(request, httpResponse); + } +} diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpResponse.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpResponse.java new file mode 100644 index 000000000..1574c8c89 --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpResponse.java @@ -0,0 +1,102 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import com.google.api.client.http.LowLevelHttpResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Logger; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.message.StatusLine; + +final class Apache5HttpResponse extends LowLevelHttpResponse { + + private static final Logger LOGGER = Logger.getLogger(Apache5HttpResponse.class.getName()); + private final HttpUriRequestBase request; + private final ClassicHttpResponse response; + private final Header[] allHeaders; + private final HttpEntity entity; + + Apache5HttpResponse(HttpUriRequestBase request, ClassicHttpResponse response) { + this.request = request; + this.response = response; + this.allHeaders = response.getHeaders(); + this.entity = response.getEntity(); + } + + @Override + public int getStatusCode() { + return response.getCode(); + } + + @Override + public InputStream getContent() throws IOException { + return new Apache5ResponseContent(entity.getContent(), response); + } + + @Override + public String getContentEncoding() { + return entity != null ? entity.getContentEncoding() : null; + } + + @Override + public long getContentLength() { + return entity == null ? -1 : entity.getContentLength(); + } + + @Override + public String getContentType() { + return entity == null ? null : entity.getContentType(); + } + + @Override + public String getReasonPhrase() { + return response.getReasonPhrase(); + } + + @Override + public String getStatusLine() { + return new StatusLine(response).toString(); + } + + public String getHeaderValue(String name) { + return response.getLastHeader(name).getValue(); + } + + @Override + public int getHeaderCount() { + return allHeaders.length; + } + + @Override + public String getHeaderName(int index) { + return allHeaders[index].getName(); + } + + @Override + public String getHeaderValue(int index) { + return allHeaders[index].getValue(); + } + + /** Aborts execution of the request. */ + @Override + public void disconnect() throws IOException { + request.abort(); + response.close(); + } +} diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpTransport.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpTransport.java new file mode 100644 index 000000000..868a2cf93 --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5HttpTransport.java @@ -0,0 +1,221 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import com.google.api.client.http.HttpMethods; +import com.google.api.client.http.HttpTransport; +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.net.ProxySelector; +import java.net.URI; +import java.util.concurrent.TimeUnit; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpDelete; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.classic.methods.HttpOptions; +import org.apache.hc.client5.http.classic.methods.HttpPatch; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpPut; +import org.apache.hc.client5.http.classic.methods.HttpTrace; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.io.CloseMode; +import org.apache.hc.core5.io.ModalCloseable; + +/** + * Thread-safe HTTP transport based on the Apache HTTP Client library. + * + *

Implementation is thread-safe, as long as any parameter modification to the {@link + * #getHttpClient() Apache HTTP Client} is only done at initialization time. For maximum efficiency, + * applications should use a single globally-shared instance of the HTTP transport. + * + *

Default settings are specified in {@link #newDefaultHttpClient()}. Use the {@link + * #Apache5HttpTransport(HttpClient)} constructor to override the Apache HTTP Client used. Please + * read the + * Apache HTTP Client 5.x configuration example for more complex configuration options. + */ +public final class Apache5HttpTransport extends HttpTransport { + + /** Apache HTTP client. */ + private final HttpClient httpClient; + + /** If the HTTP client uses mTLS channel. */ + private final boolean isMtls; + + /** Constructor that uses {@link #newDefaultHttpClient()} for the Apache HTTP client. */ + public Apache5HttpTransport() { + this(newDefaultHttpClient(), false); + } + + /** + * Constructor that allows an alternative Apache HTTP client to be used. + * + *

If you choose to provide your own Apache HttpClient implementation, be sure that + * + *

    + *
  • HTTP version is set to 1.1. + *
  • Retries are disabled (google-http-client handles retries). + *
+ * + * @param httpClient Apache HTTP client to use + */ + public Apache5HttpTransport(HttpClient httpClient) { + this.httpClient = httpClient; + this.isMtls = false; + } + + /** + * {@link Beta}
+ * Constructor that allows an alternative CLoseable Apache HTTP client to be used. + * + *

If you choose to provide your own Apache HttpClient implementation, be sure that + * + *

    + *
  • HTTP version is set to 1.1. + *
  • Retries are disabled (google-http-client handles retries). + *
  • Redirects are disabled (google-http-client handles retries). + *
+ * + * @param httpClient Apache HTTP client to use + * @param isMtls If the HTTP client is mutual TLS + */ + @Beta + public Apache5HttpTransport(HttpClient httpClient, boolean isMtls) { + this.httpClient = httpClient; + this.isMtls = isMtls; + } + + /** + * Creates a new instance of the Apache HTTP client that is used by the {@link + * #Apache5HttpTransport()} constructor. + * + *

Settings: + * + *

    + *
  • The client connection manager is set to {@link PoolingHttpClientConnectionManager}. + *
  • The retry mechanism is turned off using {@link + * HttpClientBuilder#disableAutomaticRetries()}. + *
  • Redirects are turned off using {@link HttpClientBuilder#disableRedirectHandling}. + *
  • The route planner uses {@link SystemDefaultRoutePlanner} with {@link + * ProxySelector#getDefault()}, which uses the proxy settings from system + * properties. + *
+ * + * @return new instance of the Apache HTTP client + */ + public static HttpClient newDefaultHttpClient() { + return newDefaultHttpClientBuilder().build(); + } + + /** + * Creates a new Apache HTTP client builder that is used by the {@link #Apache5HttpTransport()} + * constructor. + * + *

Settings: + * + *

    + *
  • The client connection manager is set to {@link PoolingHttpClientConnectionManager}. + *
  • The retry mechanism is turned off using {@link + * HttpClientBuilder#disableAutomaticRetries()}. + *
  • Redirects are turned off using {@link HttpClientBuilder#disableRedirectHandling}. + *
  • The route planner uses {@link SystemDefaultRoutePlanner} with {@link + * ProxySelector#getDefault()}, which uses the proxy settings from system + * properties. + *
+ * + * @return new instance of the Apache HTTP client builder + */ + public static HttpClientBuilder newDefaultHttpClientBuilder() { + PoolingHttpClientConnectionManager connectionManager = + PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(SSLConnectionSocketFactory.getSocketFactory()) + .setMaxConnTotal(200) + .setMaxConnPerRoute(20) + .setDefaultConnectionConfig( + ConnectionConfig.custom().setTimeToLive(-1, TimeUnit.MILLISECONDS).build()) + .build(); + + return HttpClients.custom() + .useSystemProperties() + .setConnectionManager(connectionManager) + .setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault())) + .disableRedirectHandling() + .disableAutomaticRetries(); + } + + @Override + public boolean supportsMethod(String method) { + return true; + } + + @Override + protected Apache5HttpRequest buildRequest(String method, String url) { + HttpUriRequestBase requestBase; + if (method.equals(HttpMethods.DELETE)) { + requestBase = new HttpDelete(url); + } else if (method.equals(HttpMethods.GET)) { + requestBase = new HttpGet(url); + } else if (method.equals(HttpMethods.HEAD)) { + requestBase = new HttpHead(url); + } else if (method.equals(HttpMethods.PATCH)) { + requestBase = new HttpPatch(url); + } else if (method.equals(HttpMethods.POST)) { + requestBase = new HttpPost(url); + } else if (method.equals(HttpMethods.PUT)) { + requestBase = new HttpPut(url); + } else if (method.equals(HttpMethods.TRACE)) { + requestBase = new HttpTrace(url); + } else if (method.equals(HttpMethods.OPTIONS)) { + requestBase = new HttpOptions(url); + } else { + requestBase = new HttpUriRequestBase(Preconditions.checkNotNull(method), URI.create(url)); + } + return new Apache5HttpRequest(httpClient, requestBase); + } + + /** + * Gracefully shuts down the connection manager and releases allocated resources. This closes all + * connections, whether they are currently used or not. + */ + @Override + public void shutdown() throws IOException { + if (httpClient instanceof ModalCloseable) { + ((ModalCloseable) httpClient).close(CloseMode.GRACEFUL); + } + // otherwise no-op + } + + /** Returns the Apache HTTP client. */ + public HttpClient getHttpClient() { + return httpClient; + } + + /** Returns if the underlying HTTP client is mTLS. */ + @Override + public boolean isMtls() { + return isMtls; + } +} diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ResponseContent.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ResponseContent.java new file mode 100644 index 000000000..c2d3091df --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/Apache5ResponseContent.java @@ -0,0 +1,75 @@ +package com.google.api.client.http.apache.v5; + +import com.google.common.annotations.VisibleForTesting; +import java.io.IOException; +import java.io.InputStream; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpResponse; + +/** + * Class that wraps an {@link org.apache.hc.core5.http.HttpEntity}'s content {@link InputStream} + * along with the {@link ClassicHttpResponse} that contains this entity. The main purpose is to be + * able to close the response as well as the content input stream when {@link #close()} is called, + * in order to not break the existing contract with clients using apache v4 that only required them + * to close the input stream to clean up all resources. + */ +public class Apache5ResponseContent extends InputStream { + private final ClassicHttpResponse response; + private final InputStream wrappedStream; + + public Apache5ResponseContent(InputStream wrappedStream, ClassicHttpResponse response) { + this.response = response; + this.wrappedStream = wrappedStream; + } + + @Override + public int read() throws IOException { + return wrappedStream.read(); + } + + @Override + public int read(byte b[]) throws IOException { + return wrappedStream.read(b); + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + return wrappedStream.read(b, off, len); + } + + @Override + public long skip(long n) throws IOException { + return wrappedStream.skip(n); + } + + @Override + public int available() throws IOException { + return wrappedStream.available(); + } + + @Override + public synchronized void mark(int readlimit) { + wrappedStream.mark(readlimit); + } + + @Override + public synchronized void reset() throws IOException { + wrappedStream.reset(); + } + + @Override + public void close() throws IOException { + wrappedStream.close(); + response.close(); + } + + @Override + public boolean markSupported() { + return wrappedStream.markSupported(); + } + + @VisibleForTesting + HttpResponse getResponse() { + return response; + } +} diff --git a/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/package-info.java b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/package-info.java new file mode 100644 index 000000000..223edc82d --- /dev/null +++ b/google-http-client-apache-v5/src/main/java/com/google/api/client/http/apache/v5/package-info.java @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Google LLC + * + * 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. + */ + +/** HTTP Transport library for Google API's based on Apache HTTP Client/Core version 5.x */ +package com.google.api.client.http.apache.v5; diff --git a/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpRequestTest.java b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpRequestTest.java new file mode 100644 index 000000000..3b7ca4a21 --- /dev/null +++ b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpRequestTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.api.client.http.ByteArrayContent; +import com.google.api.client.http.HttpContent; +import com.google.api.client.http.InputStreamContent; +import com.google.api.client.http.LowLevelHttpResponse; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.BasicHttpEntity; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.junit.Test; + +public class Apache5HttpRequestTest { + @Test + public void testContentLengthSet() throws Exception { + HttpUriRequestBase base = new HttpPost("http://www.google.com"); + Apache5HttpRequest request = + new Apache5HttpRequest( + new MockHttpClient() { + @Override + public ClassicHttpResponse executeOpen( + HttpHost target, ClassicHttpRequest request, HttpContext context) { + return new MockClassicHttpResponse(); + } + }, + base); + HttpContent content = + new ByteArrayContent("text/plain", "sample".getBytes(StandardCharsets.UTF_8)); + request.setStreamingContent(content); + request.setContentLength(content.getLength()); + request.execute(); + + assertFalse(base.getEntity().isChunked()); + assertEquals(6, base.getEntity().getContentLength()); + } + + @Test + public void testChunked() throws Exception { + byte[] buf = new byte[300]; + Arrays.fill(buf, (byte) ' '); + HttpUriRequestBase base = new HttpPost("http://www.google.com"); + Apache5HttpRequest request = + new Apache5HttpRequest( + new MockHttpClient() { + @Override + public ClassicHttpResponse executeOpen( + HttpHost target, ClassicHttpRequest request, HttpContext context) { + return new MockClassicHttpResponse(); + } + }, + base); + HttpContent content = new InputStreamContent("text/plain", new ByteArrayInputStream(buf)); + request.setStreamingContent(content); + request.execute(); + + assertTrue(base.getEntity().isChunked()); + assertEquals(-1, base.getEntity().getContentLength()); + } + + @Test + public void testExecute_closeContent_closesResponse() throws Exception { + HttpUriRequestBase base = new HttpPost("http://www.google.com"); + final InputStream responseContentStream = new ByteArrayInputStream(new byte[] {1, 2, 3}); + BasicHttpEntity testEntity = + new BasicHttpEntity(responseContentStream, ContentType.DEFAULT_BINARY); + AtomicInteger closedResponseCounter = new AtomicInteger(0); + ClassicHttpResponse classicResponse = + new MockClassicHttpResponse() { + @Override + public HttpEntity getEntity() { + return testEntity; + } + + @Override + public void close() { + closedResponseCounter.incrementAndGet(); + } + }; + + Apache5HttpRequest request = + new Apache5HttpRequest( + new MockHttpClient() { + @Override + public ClassicHttpResponse executeOpen( + HttpHost target, ClassicHttpRequest request, HttpContext context) { + return classicResponse; + } + }, + base); + LowLevelHttpResponse response = request.execute(); + assertTrue(response instanceof Apache5HttpResponse); + + // we confirm that the classic response we prepared in this test is the same as the content's + // response + assertTrue(response.getContent() instanceof Apache5ResponseContent); + assertEquals(classicResponse, ((Apache5ResponseContent) response.getContent()).getResponse()); + + // we close the response's content stream and confirm the response is also closed + assertEquals(0, closedResponseCounter.get()); + response.getContent().close(); + assertEquals(1, closedResponseCounter.get()); + } +} diff --git a/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpTransportTest.java b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpTransportTest.java new file mode 100644 index 000000000..99045d99d --- /dev/null +++ b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/Apache5HttpTransportTest.java @@ -0,0 +1,353 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.client.http.apache.v5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpResponseException; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.LowLevelHttpResponse; +import com.google.api.client.util.ByteArrayStreamingContent; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.hc.client5.http.ConnectTimeoutException; +import org.apache.hc.client5.http.HttpHostConnectException; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.EntityDetails; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpRequestInterceptor; +import org.apache.hc.core5.http.HttpRequestMapper; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.impl.bootstrap.HttpServer; +import org.apache.hc.core5.http.impl.io.HttpRequestExecutor; +import org.apache.hc.core5.http.impl.io.HttpService; +import org.apache.hc.core5.http.io.HttpClientConnection; +import org.apache.hc.core5.http.io.HttpRequestHandler; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.support.BasicHttpServerRequestHandler; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.http.protocol.HttpProcessor; +import org.junit.Assert; +import org.junit.Test; + +/** Tests {@link Apache5HttpTransport}. */ +public class Apache5HttpTransportTest { + + @Test + public void testApacheHttpTransport() { + Apache5HttpTransport transport = new Apache5HttpTransport(); + checkHttpTransport(transport); + assertFalse(transport.isMtls()); + } + + @Test + public void testApacheHttpTransportWithParam() { + Apache5HttpTransport transport = new Apache5HttpTransport(HttpClients.custom().build(), true); + checkHttpTransport(transport); + assertTrue(transport.isMtls()); + } + + @Test + public void testNewDefaultHttpClient() { + HttpClient client = Apache5HttpTransport.newDefaultHttpClient(); + checkHttpClient(client); + } + + private void checkHttpTransport(Apache5HttpTransport transport) { + assertNotNull(transport); + HttpClient client = transport.getHttpClient(); + checkHttpClient(client); + } + + private void checkHttpClient(HttpClient client) { + assertNotNull(client); + // TODO(chingor): Is it possible to test this effectively? The newer HttpClient implementations + // are read-only and we're testing that we built the client with the right configuration + } + + @Test + public void testRequestsWithContent() throws IOException { + // This test confirms that we can set the content on any type of request + HttpClient mockClient = + new MockHttpClient() { + @Override + public ClassicHttpResponse executeOpen( + HttpHost target, ClassicHttpRequest request, HttpContext context) { + return new MockClassicHttpResponse(); + } + }; + Apache5HttpTransport transport = new Apache5HttpTransport(mockClient); + + // Test GET. + execute(transport.buildRequest("GET", "http://www.test.url")); + // Test DELETE. + execute(transport.buildRequest("DELETE", "http://www.test.url")); + // Test HEAD. + execute(transport.buildRequest("HEAD", "http://www.test.url")); + + // Test PATCH. + execute(transport.buildRequest("PATCH", "http://www.test.url")); + // Test PUT. + execute(transport.buildRequest("PUT", "http://www.test.url")); + // Test POST. + execute(transport.buildRequest("POST", "http://www.test.url")); + // Test PATCH. + execute(transport.buildRequest("PATCH", "http://www.test.url")); + } + + private void execute(Apache5HttpRequest request) throws IOException { + byte[] bytes = "abc".getBytes(StandardCharsets.UTF_8); + request.setStreamingContent(new ByteArrayStreamingContent(bytes)); + request.setContentType("text/html"); + request.setContentLength(bytes.length); + request.execute(); + } + + @Test + public void testRequestShouldNotFollowRedirects() throws IOException { + final AtomicInteger requestsAttempted = new AtomicInteger(0); + HttpRequestExecutor requestExecutor = + new HttpRequestExecutor() { + @Override + public ClassicHttpResponse execute( + ClassicHttpRequest request, HttpClientConnection connection, HttpContext context) + throws IOException, HttpException { + ClassicHttpResponse response = new MockClassicHttpResponse(); + response.setCode(302); + response.setReasonPhrase(null); + response.addHeader("location", "https://google.com/path"); + response.addHeader(HttpHeaders.SET_COOKIE, ""); + requestsAttempted.incrementAndGet(); + return response; + } + }; + HttpClient client = HttpClients.custom().setRequestExecutor(requestExecutor).build(); + Apache5HttpTransport transport = new Apache5HttpTransport(client); + Apache5HttpRequest request = transport.buildRequest("GET", "https://google.com"); + LowLevelHttpResponse response = request.execute(); + assertEquals(1, requestsAttempted.get()); + assertEquals(302, response.getStatusCode()); + } + + @Test + public void testRequestCanSetHeaders() { + final AtomicBoolean interceptorCalled = new AtomicBoolean(false); + HttpClient client = + HttpClients.custom() + .addRequestInterceptorFirst( + new HttpRequestInterceptor() { + @Override + public void process( + HttpRequest request, EntityDetails details, HttpContext context) + throws HttpException, IOException { + Header header = request.getFirstHeader("foo"); + assertNotNull("Should have found header", header); + assertEquals("bar", header.getValue()); + interceptorCalled.set(true); + throw new IOException("cancelling request"); + } + }) + .build(); + + Apache5HttpTransport transport = new Apache5HttpTransport(client); + Apache5HttpRequest request = transport.buildRequest("GET", "https://google.com"); + request.addHeader("foo", "bar"); + try { + LowLevelHttpResponse response = request.execute(); + fail("should not actually make the request"); + } catch (IOException exception) { + assertEquals("cancelling request", exception.getMessage()); + } + assertTrue("Expected to have called our test interceptor", interceptorCalled.get()); + } + + @Test(timeout = 10_000L) + public void testConnectTimeout() { + // TODO(chanseok): Java 17 returns an IOException (SocketException: Network is unreachable). + // Figure out a way to verify connection timeout works on Java 17+. + assumeTrue(System.getProperty("java.version").compareTo("17") < 0); + + HttpTransport httpTransport = new Apache5HttpTransport(); + GenericUrl url = new GenericUrl("http://google.com:81"); + try { + httpTransport.createRequestFactory().buildGetRequest(url).setConnectTimeout(100).execute(); + fail("should have thrown an exception"); + } catch (HttpHostConnectException | ConnectTimeoutException expected) { + // expected + } catch (IOException e) { + fail("unexpected IOException: " + e.getClass().getName() + ": " + e.getMessage()); + } + } + + private static class FakeServer implements AutoCloseable { + private final HttpServer server; + + FakeServer(final HttpRequestHandler httpHandler) throws IOException { + HttpRequestMapper mapper = + new HttpRequestMapper() { + @Override + public HttpRequestHandler resolve(HttpRequest request, HttpContext context) + throws HttpException { + return httpHandler; + }; + }; + server = + new HttpServer( + 0, + HttpService.builder() + .withHttpProcessor( + new HttpProcessor() { + @Override + public void process( + HttpRequest request, EntityDetails entity, HttpContext context) + throws HttpException, IOException {} + + @Override + public void process( + HttpResponse response, EntityDetails entity, HttpContext context) + throws HttpException, IOException {} + }) + .withHttpServerRequestHandler(new BasicHttpServerRequestHandler(mapper)) + .build(), + null, + null, + null, + null, + null, + null); + // server.createContext("/", httpHandler); + server.start(); + } + + public int getPort() { + return server.getLocalPort(); + } + + @Override + public void close() { + server.initiateShutdown(); + } + } + + @Test + public void testNormalizedUrl() throws IOException { + final HttpRequestHandler handler = + new HttpRequestHandler() { + @Override + public void handle( + ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) + throws HttpException, IOException { + // Extract the request URI and convert to bytes + byte[] responseData = request.getRequestUri().getBytes(StandardCharsets.UTF_8); + + // Set the response headers (status code and content length) + response.setCode(HttpStatus.SC_OK); + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(responseData.length)); + + // Set the response entity (body) + ByteArrayEntity entity = new ByteArrayEntity(responseData, ContentType.TEXT_PLAIN); + response.setEntity(entity); + } + }; + try (FakeServer server = new FakeServer(handler)) { + HttpTransport transport = new Apache5HttpTransport(); + GenericUrl testUrl = new GenericUrl("http://localhost/foo//bar"); + testUrl.setPort(server.getPort()); + com.google.api.client.http.HttpResponse response = + transport.createRequestFactory().buildGetRequest(testUrl).execute(); + assertEquals(200, response.getStatusCode()); + assertEquals("/foo//bar", response.parseAsString()); + } + } + + @Test + public void testReadErrorStream() throws IOException { + final HttpRequestHandler handler = + new HttpRequestHandler() { + @Override + public void handle( + ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) + throws HttpException, IOException { + byte[] responseData = "Forbidden".getBytes(StandardCharsets.UTF_8); + response.setCode(HttpStatus.SC_FORBIDDEN); // 403 Forbidden + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(responseData.length)); + ByteArrayEntity entity = new ByteArrayEntity(responseData, ContentType.TEXT_PLAIN); + response.setEntity(entity); + } + }; + try (FakeServer server = new FakeServer(handler)) { + HttpTransport transport = new Apache5HttpTransport(); + GenericUrl testUrl = new GenericUrl("http://localhost/foo//bar"); + testUrl.setPort(server.getPort()); + com.google.api.client.http.HttpRequest getRequest = + transport.createRequestFactory().buildGetRequest(testUrl); + getRequest.setThrowExceptionOnExecuteError(false); + com.google.api.client.http.HttpResponse response = getRequest.execute(); + assertEquals(403, response.getStatusCode()); + assertEquals("Forbidden", response.parseAsString()); + } + } + + @Test + public void testReadErrorStream_withException() throws IOException { + final HttpRequestHandler handler = + new HttpRequestHandler() { + @Override + public void handle( + ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) + throws HttpException, IOException { + byte[] responseData = "Forbidden".getBytes(StandardCharsets.UTF_8); + response.setCode(HttpStatus.SC_FORBIDDEN); // 403 Forbidden + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(responseData.length)); + ByteArrayEntity entity = new ByteArrayEntity(responseData, ContentType.TEXT_PLAIN); + response.setEntity(entity); + } + }; + try (FakeServer server = new FakeServer(handler)) { + HttpTransport transport = new Apache5HttpTransport(); + GenericUrl testUrl = new GenericUrl("http://localhost/foo//bar"); + testUrl.setPort(server.getPort()); + com.google.api.client.http.HttpRequest getRequest = + transport.createRequestFactory().buildGetRequest(testUrl); + try { + getRequest.execute(); + Assert.fail(); + } catch (HttpResponseException ex) { + assertEquals("Forbidden", ex.getContent()); + } + } + } + + private boolean isWindows() { + return System.getProperty("os.name").startsWith("Windows"); + } +} diff --git a/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockClassicHttpResponse.java b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockClassicHttpResponse.java new file mode 100644 index 000000000..091721745 --- /dev/null +++ b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockClassicHttpResponse.java @@ -0,0 +1,182 @@ +package com.google.api.client.http.apache.v5; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpVersion; +import org.apache.hc.core5.http.ProtocolException; +import org.apache.hc.core5.http.ProtocolVersion; + +public class MockClassicHttpResponse implements ClassicHttpResponse { + List
headers = new ArrayList<>(); + int code = 200; + + @Override + public int getCode() { + return code; + } + + @Override + public void setCode(int code) { + this.code = code; + } + + @Override + public String getReasonPhrase() { + return null; + } + + @Override + public void setReasonPhrase(String reason) {} + + @Override + public Locale getLocale() { + return null; + } + + @Override + public void setLocale(Locale loc) {} + + @Override + public void setVersion(ProtocolVersion version) {} + + @Override + public ProtocolVersion getVersion() { + return HttpVersion.HTTP_1_1; + } + + @Override + public void addHeader(Header header) { + headers.add(header); + } + + @Override + public void addHeader(String name, Object value) { + addHeader(newHeader(name, value)); + } + + private Header newHeader(String key, Object value) { + return new Header() { + @Override + public boolean isSensitive() { + return false; + } + + @Override + public String getName() { + return key; + } + + @Override + public String getValue() { + return value.toString(); + } + }; + } + + @Override + public void setHeader(Header header) { + if (headers.contains(header)) { + int index = headers.indexOf(header); + headers.set(index, header); + } else { + addHeader(header); + } + } + + @Override + public void setHeader(String name, Object value) { + setHeader(newHeader(name, value)); + } + + @Override + public void setHeaders(Header... headers) { + for (Header header : headers) { + setHeader(header); + } + } + + @Override + public boolean removeHeader(Header header) { + if (headers.contains(header)) { + headers.remove(headers.indexOf(header)); + return true; + } + return false; + } + + @Override + public boolean removeHeaders(String name) { + int initialSize = headers.size(); + for (Header header : + headers.stream().filter(h -> h.getName() == name).collect(Collectors.toList())) { + removeHeader(header); + } + return headers.size() < initialSize; + } + + @Override + public boolean containsHeader(String name) { + return headers.stream().anyMatch(h -> h.getName() == name); + } + + @Override + public int countHeaders(String name) { + return headers.size(); + } + + @Override + public Header getFirstHeader(String name) { + return headers.stream().findFirst().orElse(null); + } + + @Override + public Header getHeader(String name) throws ProtocolException { + return headers.stream().filter(h -> h.getName() == name).findFirst().orElse(null); + } + + @Override + public Header[] getHeaders() { + return headers.toArray(new Header[0]); + } + + @Override + public Header[] getHeaders(String name) { + return headers.stream() + .filter(h -> h.getName() == name) + .collect(Collectors.toList()) + .toArray(new Header[0]); + } + + @Override + public Header getLastHeader(String name) { + return headers.isEmpty() ? null : headers.get(headers.size() - 1); + } + + @Override + public Iterator
headerIterator() { + return headers.iterator(); + } + + @Override + public Iterator
headerIterator(String name) { + return headers.stream().filter(h -> h.getName() == name).iterator(); + } + + @Override + public void close() throws IOException {} + + @Override + public HttpEntity getEntity() { + return null; + } + + @Override + public void setEntity(HttpEntity entity) {} +} diff --git a/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockHttpClient.java b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockHttpClient.java new file mode 100644 index 000000000..8d26096cf --- /dev/null +++ b/google-http-client-apache-v5/src/test/java/com/google/api/client/http/apache/v5/MockHttpClient.java @@ -0,0 +1,86 @@ +package com.google.api.client.http.apache.v5; + +import com.google.api.client.util.Preconditions; +import java.io.IOException; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.protocol.HttpContext; + +public class MockHttpClient implements HttpClient { + + /** HTTP response code to use. */ + int responseCode; + + /** Returns the HTTP response code to use. */ + public final int getResponseCode() { + return responseCode; + } + + /** Sets the HTTP response code to use. */ + public MockHttpClient setResponseCode(int responseCode) { + Preconditions.checkArgument(responseCode >= 0); + this.responseCode = responseCode; + return this; + } + + @Override + public HttpResponse execute(ClassicHttpRequest request) throws IOException { + return null; + } + + @Override + public HttpResponse execute(ClassicHttpRequest request, HttpContext context) throws IOException { + return null; + } + + @Override + public ClassicHttpResponse execute(HttpHost target, ClassicHttpRequest request) + throws IOException { + return null; + } + + @Override + public HttpResponse execute(HttpHost target, ClassicHttpRequest request, HttpContext context) + throws IOException { + return null; + } + + @Override + public T execute( + ClassicHttpRequest request, HttpClientResponseHandler responseHandler) + throws IOException { + return null; + } + + @Override + public T execute( + ClassicHttpRequest request, + HttpContext context, + HttpClientResponseHandler responseHandler) + throws IOException { + return null; + } + + @Override + public T execute( + HttpHost target, + ClassicHttpRequest request, + HttpClientResponseHandler responseHandler) + throws IOException { + return null; + } + + @Override + public T execute( + HttpHost target, + ClassicHttpRequest request, + HttpContext context, + HttpClientResponseHandler responseHandler) + throws IOException { + return null; + } +} diff --git a/google-http-client-appengine/pom.xml b/google-http-client-appengine/pom.xml index 20ebf8f84..573b3a334 100644 --- a/google-http-client-appengine/pom.xml +++ b/google-http-client-appengine/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-appengine - 1.44.2 + 1.45.0 Google App Engine extensions to the Google HTTP Client Library for Java. diff --git a/google-http-client-assembly/classpath-include b/google-http-client-assembly/classpath-include index c1bd80328..c7bbd573f 100644 --- a/google-http-client-assembly/classpath-include +++ b/google-http-client-assembly/classpath-include @@ -7,8 +7,8 @@ - - + + diff --git a/google-http-client-assembly/pom.xml b/google-http-client-assembly/pom.xml index f2cc29862..3f58b39d8 100644 --- a/google-http-client-assembly/pom.xml +++ b/google-http-client-assembly/pom.xml @@ -4,12 +4,12 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml com.google.http-client google-http-client-assembly - 1.44.2 + 1.45.0 pom Assembly for the Google HTTP Client Library for Java diff --git a/google-http-client-assembly/readme.html b/google-http-client-assembly/readme.html index 5e7af564d..8a146df1e 100644 --- a/google-http-client-assembly/readme.html +++ b/google-http-client-assembly/readme.html @@ -135,8 +135,8 @@

General Purpose Java Environment Dependencies

required for general purpose Java applications :
  • commons-logging-${project.commons-logging.version}.jar
  • -
  • httpclient-${project.httpclient.version}.jar
  • -
  • httpcore-${project.httpcore.version}.jar
  • +
  • httpclient-${project.apache-httpclient-4.version}.jar
  • +
  • httpcore-${project.apache-httpcore-4.version}.jar
diff --git a/google-http-client-bom/pom.xml b/google-http-client-bom/pom.xml index 92ba7375c..ac2f8cbab 100644 --- a/google-http-client-bom/pom.xml +++ b/google-http-client-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.http-client google-http-client-bom - 1.44.2 + 1.45.0 pom Google HTTP Client Library for Java BOM @@ -63,52 +63,52 @@ com.google.http-client google-http-client - 1.44.2 + 1.45.0 com.google.http-client google-http-client-android - 1.44.2 + 1.45.0 com.google.http-client google-http-client-apache-v2 - 1.44.2 + 1.45.0 com.google.http-client google-http-client-appengine - 1.44.2 + 1.45.0 com.google.http-client google-http-client-findbugs - 1.44.2 + 1.45.0 com.google.http-client google-http-client-gson - 1.44.2 + 1.45.0 com.google.http-client google-http-client-jackson2 - 1.44.2 + 1.45.0 com.google.http-client google-http-client-protobuf - 1.44.2 + 1.45.0 com.google.http-client google-http-client-test - 1.44.2 + 1.45.0 com.google.http-client google-http-client-xml - 1.44.2 + 1.45.0 @@ -117,7 +117,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true sonatype-nexus-staging @@ -128,7 +128,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.8.0 true @@ -166,7 +166,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.5 sign-artifacts diff --git a/google-http-client-findbugs/google-http-client-findbugs-test/pom.xml b/google-http-client-findbugs/google-http-client-findbugs-test/pom.xml index bc97d5de0..461d1241a 100644 --- a/google-http-client-findbugs/google-http-client-findbugs-test/pom.xml +++ b/google-http-client-findbugs/google-http-client-findbugs-test/pom.xml @@ -11,7 +11,7 @@ maven-compiler-plugin - 3.11.0 + 3.13.0 1.7 1.7 @@ -19,7 +19,7 @@ maven-jar-plugin - 3.3.0 + 3.4.2 diff --git a/google-http-client-findbugs/pom.xml b/google-http-client-findbugs/pom.xml index 320dd3d38..00c3f9a98 100644 --- a/google-http-client-findbugs/pom.xml +++ b/google-http-client-findbugs/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-findbugs - 1.44.2 + 1.45.0 Google APIs Client Library Findbugs custom plugin. diff --git a/google-http-client-gson/pom.xml b/google-http-client-gson/pom.xml index 9aec75be0..81c9e005f 100644 --- a/google-http-client-gson/pom.xml +++ b/google-http-client-gson/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-gson - 1.44.2 + 1.45.0 GSON extensions to the Google HTTP Client Library for Java. @@ -30,7 +30,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-test-source diff --git a/google-http-client-jackson2/pom.xml b/google-http-client-jackson2/pom.xml index 62b449911..a9450c3be 100644 --- a/google-http-client-jackson2/pom.xml +++ b/google-http-client-jackson2/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-jackson2 - 1.44.2 + 1.45.0 Jackson 2 extensions to the Google HTTP Client Library for Java. @@ -29,7 +29,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-test-source diff --git a/google-http-client-protobuf/pom.xml b/google-http-client-protobuf/pom.xml index 01bba38f4..814c4a951 100644 --- a/google-http-client-protobuf/pom.xml +++ b/google-http-client-protobuf/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-protobuf - 1.44.2 + 1.45.0 Protocol Buffer extensions to the Google HTTP Client Library for Java. diff --git a/google-http-client-test/pom.xml b/google-http-client-test/pom.xml index 1fc9bd0db..82bd423c5 100644 --- a/google-http-client-test/pom.xml +++ b/google-http-client-test/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-test - 1.44.2 + 1.45.0 Shared classes used for testing of artifacts in the Google HTTP Client Library for Java. @@ -29,7 +29,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-test-source diff --git a/google-http-client-xml/pom.xml b/google-http-client-xml/pom.xml index b5b5358c5..c28f0e20f 100644 --- a/google-http-client-xml/pom.xml +++ b/google-http-client-xml/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client-xml - 1.44.2 + 1.45.0 XML extensions to the Google HTTP Client Library for Java. @@ -29,7 +29,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-test-source diff --git a/google-http-client/pom.xml b/google-http-client/pom.xml index f5995ab1d..d1dd414fa 100644 --- a/google-http-client/pom.xml +++ b/google-http-client/pom.xml @@ -4,11 +4,11 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../pom.xml google-http-client - 1.44.2 + 1.45.0 Google HTTP Client Library for Java Google HTTP Client Library for Java. Functionality that works on all supported Java platforms, diff --git a/pom.xml b/pom.xml index 5d1bcaca9..ea79fec71 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 pom Parent for the Google HTTP Client Library for Java Google HTTP Client Library for Java @@ -62,6 +62,7 @@ google-http-client-appengine google-http-client-android google-http-client-apache-v2 + google-http-client-apache-v5 google-http-client-protobuf google-http-client-gson google-http-client-jackson2 @@ -92,7 +93,7 @@ com.google.cloud native-image-shared-config - 1.7.6 + 1.11.0 maven-project-info-reports-plugin - 3.4.5 + 3.6.2 @@ -592,24 +609,63 @@ - google-api-java-client/google-api-client-assembly/android-properties (make the filenames match the version here) - Internally, update the default features.json file --> - 1.44.2 - 2.0.25 + 1.45.0 + 2.0.29 UTF-8 3.0.2 - 2.10.1 - 2.14.2 + 2.11.0 + 2.17.2 3.21.12 30.1.1-android 1.1.4c - 4.5.14 - 4.4.16 + 4.5.14 + 4.4.16 + 5.3.1 + 5.2.5 0.31.1 .. - 3.0.0-M7 + 3.4.0 false + + java21 + + [21,) + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.8.0 + + 1.8 + false + + + + attach-javadocs + + jar + + + + + + + + native-tests @@ -661,7 +717,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.5 sign-artifacts @@ -750,7 +806,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.3 + 3.8.0 com.microsoft.doclet.DocFxDoclet false diff --git a/renovate.json b/renovate.json index cd7d2400b..09aa66d34 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": [ + "config:recommended", ":separateMajorReleases", ":combinePatchMinorReleases", ":ignoreUnstable", @@ -7,49 +8,53 @@ ":updateNotScheduled", ":automergeDisabled", ":ignoreModulesAndTests", - ":maintainLockFilesDisabled", - ":autodetectPinVersions" + ":maintainLockFilesDisabled" + ], + "ignorePaths": [ + ".kokoro/requirements.txt" ], - "ignorePaths": [".kokoro/requirements.txt"], "customManagers": [ { "customType": "regex", "fileMatch": [ "^.kokoro/presubmit/graalvm-native.*.cfg$" ], - "matchStrings": ["value: \"gcr.io/cloud-devrel-public-resources/graalvm.*:(?.*?)\""], + "matchStrings": [ + "value: \"gcr.io/cloud-devrel-public-resources/graalvm.*:(?.*?)\"" + ], "depNameTemplate": "com.google.cloud:native-image-shared-config", "datasourceTemplate": "maven" } ], "packageRules": [ { - "packagePatterns": [ + "matchPackagePatterns": [ "^com.google.guava:" ], - "versionScheme": "docker" + "versioning": "docker" }, { - "packagePatterns": [ + "matchPackagePatterns": [ "*" ], "semanticCommitType": "deps", "semanticCommitScope": null }, { - "packagePatterns": [ + "matchPackagePatterns": [ "^org.apache.maven", "^org.jacoco:", "^org.codehaus.mojo:", "^org.sonatype.plugins:", "^com.coveo:", - "^com.google.cloud:google-cloud-shared-config" + "^com.google.cloud:native-image-shared-config" ], "semanticCommitType": "build", - "semanticCommitScope": "deps" + "semanticCommitScope": "deps", + "enabled": true }, { - "packagePatterns": [ + "matchPackagePatterns": [ "^com.google.http-client:google-http-client", "^com.google.cloud:libraries-bom", "^com.google.cloud.samples:shared-configuration" @@ -58,7 +63,7 @@ "semanticCommitScope": "deps" }, { - "packagePatterns": [ + "matchPackagePatterns": [ "^junit:junit", "^com.google.truth:truth", "^org.mockito:mockito-core", @@ -69,18 +74,18 @@ "semanticCommitScope": "deps" }, { - "packagePatterns": [ + "matchPackagePatterns": [ "^com.google.cloud:google-cloud-" ], "ignoreUnstable": false }, { - "packagePatterns": [ + "matchPackagePatterns": [ "^com.fasterxml.jackson.core" ], "groupName": "jackson dependencies" } ], - "semanticCommits": true, + "semanticCommits": "enabled", "dependencyDashboard": true } diff --git a/samples/dailymotion-simple-cmdline-sample/pom.xml b/samples/dailymotion-simple-cmdline-sample/pom.xml index 58722fcdd..14d9218ce 100644 --- a/samples/dailymotion-simple-cmdline-sample/pom.xml +++ b/samples/dailymotion-simple-cmdline-sample/pom.xml @@ -4,7 +4,7 @@ com.google.http-client google-http-client-parent - 1.44.2 + 1.45.0 ../../pom.xml dailymotion-simple-cmdline-sample @@ -15,7 +15,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.4.1 diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 5891c62c8..b14c176e5 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-snippets-source diff --git a/samples/pom.xml b/samples/pom.xml index 88fe18cea..d0d9e30e4 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -38,7 +38,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.2 + 3.1.3 true @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index cc6cb1fa8..b8adb0e8e 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.6.0 add-snippets-source diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index c269830a9..54ade4611 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -31,7 +31,7 @@ com.google.cloud libraries-bom - 26.10.0 + 26.44.0 pom import diff --git a/versions.txt b/versions.txt index cad4285a1..aa6a7232b 100644 --- a/versions.txt +++ b/versions.txt @@ -1,17 +1,18 @@ # Format: # module:released-version:current-version -google-http-client:1.44.2:1.44.2 -google-http-client-bom:1.44.2:1.44.2 -google-http-client-parent:1.44.2:1.44.2 -google-http-client-android:1.44.2:1.44.2 -google-http-client-android-test:1.44.2:1.44.2 -google-http-client-apache-v2:1.44.2:1.44.2 -google-http-client-appengine:1.44.2:1.44.2 -google-http-client-assembly:1.44.2:1.44.2 -google-http-client-findbugs:1.44.2:1.44.2 -google-http-client-gson:1.44.2:1.44.2 -google-http-client-jackson2:1.44.2:1.44.2 -google-http-client-protobuf:1.44.2:1.44.2 -google-http-client-test:1.44.2:1.44.2 -google-http-client-xml:1.44.2:1.44.2 +google-http-client:1.45.0:1.45.0 +google-http-client-bom:1.45.0:1.45.0 +google-http-client-parent:1.45.0:1.45.0 +google-http-client-android:1.45.0:1.45.0 +google-http-client-android-test:1.45.0:1.45.0 +google-http-client-apache-v2:1.45.0:1.45.0 +google-http-client-apache-v5:1.45.0:1.45.0 +google-http-client-appengine:1.45.0:1.45.0 +google-http-client-assembly:1.45.0:1.45.0 +google-http-client-findbugs:1.45.0:1.45.0 +google-http-client-gson:1.45.0:1.45.0 +google-http-client-jackson2:1.45.0:1.45.0 +google-http-client-protobuf:1.45.0:1.45.0 +google-http-client-test:1.45.0:1.45.0 +google-http-client-xml:1.45.0:1.45.0