JCLOUDS-1641: Use POST instead of PATCH for GCS

Modern Java versions do not allow the reflection workaround previously
used.
diff --git a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
index 1af1ea8..279a03c 100644
--- a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
+++ b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java
@@ -242,6 +242,8 @@
          try {
             // SSL connections may have the HttpURLConnection wrapped inside
             delegateField = connectionClass.getDeclaredField("delegate");
+            // TODO: Fails on modern Java versions:
+            // Unable to make field private final sun.net.www.protocol.https.DelegateHttpsURLConnection sun.net.www.protocol.https.HttpsURLConnectionImpl.delegate accessible: module java.base does not "opens sun.net.www.protocol.https" to unnamed module @1ed4004b connecting to PATCH
             delegateField.setAccessible(true);
             HttpURLConnection delegateConnection = (HttpURLConnection) delegateField.get(httpURLConnection);
             setRequestMethodBypassingJREMethodLimitation(delegateConnection, method);
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageOAuthScopes.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageOAuthScopes.java
index 358c9a0..2b97bb3 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageOAuthScopes.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/config/GoogleCloudStorageOAuthScopes.java
@@ -47,6 +47,8 @@
          return fullControlScopes();
       } else if (input.getMethod().equalsIgnoreCase("PUT") || input.getMethod().equalsIgnoreCase("PATCH")) {
          return fullControlScopes();
+      } else if ("PATCH".equalsIgnoreCase(input.getFirstHeaderOrNull("X-HTTP-Method-Override"))) {
+         return fullControlScopes();
       }
       return readOrWriteScopes().forRequest(input);
    }
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
index e328b2b..1a69802 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
@@ -38,7 +38,7 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.annotations.SkipEncoding;
@@ -162,7 +162,8 @@
     * @return If successful, this method returns a BucketAccessControls resource in the response body
     */
    @Named("BucketAccessControls:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}/acl/{entity}")
    @Fallback(NullOnNotFoundOr404.class)
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
index 4c38a8d..1ed43b6 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketApi.java
@@ -45,7 +45,7 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SkipEncoding;
 import org.jclouds.rest.binders.BindToJsonPayload;
@@ -250,7 +250,8 @@
     * @return If successful, this method returns the updated {@link Bucket} resource.
     */
    @Named("Bucket:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}")
    @Fallback(NullOnNotFoundOr404.class)
@@ -272,7 +273,8 @@
     * @return If successful, this method returns the updated {@link Bucket} resource.
     */
    @Named("Bucket:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}")
    @Fallback(NullOnNotFoundOr404.class)
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApi.java
index 65c032c..2f1920c 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApi.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApi.java
@@ -40,7 +40,7 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.annotations.SkipEncoding;
@@ -170,7 +170,8 @@
     *           Name of the bucket which contains the object
     */
    @Named("DefaultObjectAccessControls:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}/defaultObjectAcl/{entity}")
    @Fallback(NullOnNotFoundOr404.class)
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApi.java
index 6551c5d..c1cc264 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApi.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApi.java
@@ -39,7 +39,7 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SelectJson;
 import org.jclouds.rest.binders.BindToJsonPayload;
@@ -282,7 +282,8 @@
     * @return an {@link ObjectAccessControls }
     */
    @Named("ObjectAccessControls:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}/o/{object}/acl/{entity}")
    ObjectAccessControls patchObjectAccessControls(@PathParam("bucket") String bucketName,
@@ -307,7 +308,8 @@
     * @return {@link ObjectAccessControls }
     */
    @Named("ObjectAccessControls:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Produces(APPLICATION_JSON)
    @Path("/b/{bucket}/o/{object}/acl/{entity}")
    ObjectAccessControls patchObjectAccessControls(@PathParam("bucket") String bucketName,
diff --git a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
index 24a4b84..a4c813e 100644
--- a/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
+++ b/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/ObjectApi.java
@@ -54,8 +54,8 @@
 import org.jclouds.oauth.v2.filters.OAuthFilter;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.PATCH;
 import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
@@ -310,7 +310,8 @@
     * @return  a {@link GoogleCloudStorageObject}
     */
    @Named("Object:patch")
-   @PATCH
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON)
    @Path("storage/v1/b/{bucket}/o/{object}")
@@ -334,7 +335,8 @@
     * @return a {@link GoogleCloudStorageObject}
     */
    @Named("Object:patch")
-   @PUT
+   @POST
+   @Headers(keys = "X-HTTP-Method-Override", values = "PATCH")
    @Consumes(APPLICATION_JSON)
    @Produces(APPLICATION_JSON)
    @Path("storage/v1/b/{bucket}/o/{object}")
diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
index 87b7510..3d53e10 100644
--- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
+++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
@@ -167,10 +167,11 @@
    public void testPatchBucketAclResponseIs2xx() throws Exception {
       HttpRequest patchRequest = HttpRequest
                .builder()
-               .method("PATCH")
+               .method("POST")
                .endpoint("https://www.googleapis.com/storage/v1/b/jcloudstestbucket/acl/allUsers")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + TOKEN)
+               .addHeader("X-HTTP-Method-Override", "PATCH")
                .payload(payloadFromResourceWithContentType("/bucket_acl_update_initial.json",
                         MediaType.APPLICATION_JSON)).build();
 
diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
index 77abe85..1eee923 100644
--- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
+++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketApiExpectTest.java
@@ -212,10 +212,11 @@
 
       HttpRequest patchRequest = HttpRequest
                .builder()
-               .method("PATCH")
+               .method("POST")
                .endpoint("https://www.googleapis.com/storage/v1/b/" + EXPECTED_TEST_BUCKET)
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + TOKEN)
+               .addHeader("X-HTTP-Method-Override", "PATCH")
                .payload(payloadFromResourceWithContentType("/bucket_update_request_payload.json",
                         MediaType.APPLICATION_JSON)).build();
 
diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApiExpectTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApiExpectTest.java
index 6918e1c..3a40930 100644
--- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApiExpectTest.java
+++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/DefaultObjectAccessControlsApiExpectTest.java
@@ -198,10 +198,11 @@
    public void testPatchDefaultObjectAclWithNoOptionsResponseIs2xx() throws Exception {
       HttpRequest update = HttpRequest
                .builder()
-               .method("PATCH")
+               .method("POST")
                .endpoint("https://www.googleapis.com/storage/v1/b/jcloudstestbucket/defaultObjectAcl/allUsers")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + TOKEN)
+               .addHeader("X-HTTP-Method-Override", "PATCH")
                .payload(payloadFromResourceWithContentType("/default_object_acl_update_request_payload.json",
                         MediaType.APPLICATION_JSON)).build();
 
diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApiExpectTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApiExpectTest.java
index 4c57a7a..4b572a7 100644
--- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApiExpectTest.java
+++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectAccessControlsApiExpectTest.java
@@ -231,10 +231,11 @@
    public void testPatchObjectaclWithNoOptionsResponseIs2xx() throws Exception {
       HttpRequest patchRequest = HttpRequest
                .builder()
-               .method("PATCH")
+               .method("POST")
                .endpoint("https://www.googleapis.com/storage/v1/b/jcloudstestbucket/o/foo.txt/acl/allUsers")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + TOKEN)
+               .addHeader("X-HTTP-Method-Override", "PATCH")
                .payload(payloadFromResourceWithContentType("/object_acl_request_payload.json",
                         MediaType.APPLICATION_JSON)).build();
 
@@ -253,11 +254,12 @@
    public void testPatchObjectaclWithOptionsResponseIs2xx() throws Exception {
       HttpRequest patchRequest = HttpRequest
                .builder()
-               .method("PATCH")
+               .method("POST")
                .endpoint("https://www.googleapis.com/storage/v1/b/jcloudstestbucket/o/foo.txt/acl/allUsers")
                .addQueryParam("generation", "100")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + TOKEN)
+               .addHeader("X-HTTP-Method-Override", "PATCH")
                .payload(payloadFromResourceWithContentType("/object_acl_request_payload.json",
                         MediaType.APPLICATION_JSON)).build();
 
diff --git a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java
index df2549d..a3cedf5 100644
--- a/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java
+++ b/providers/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/ObjectApiMockTest.java
@@ -182,7 +182,7 @@
 
       assertEquals(objectApi().patchObject("test", "file_name", template),
             new ParseGoogleCloudStorageObject().expected());
-      assertSent(server, "PATCH", "/storage/v1/b/test/o/file_name", APPLICATION_JSON,
+      assertSent(server, "POST", "/storage/v1/b/test/o/file_name", APPLICATION_JSON,
             "{" +
             "  \"name\": \"file_name\"," +
             "  \"size\": 1000," +